V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
lyricorpse
V2EX  ›  问与答

一个简单的 C 程序 bus error,以及如何用 Cython 进行封装

  •  
  •   lyricorpse · 2017-01-12 12:53:49 +08:00 · 2036 次点击
    这是一个创建于 2872 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个相对复杂的 C 程序想用 Cython 将其中的某几个函数封装了给 Python 调用,由于太复杂想写个结构类似但简单的小程序试着用 Cython 封装,代码area.c如下:

    #include <stdio.h>
    #include <string.h>
    
    struct Square {
        float length;
        float width;
    };
    
    typedef struct Square *sq;
    
    float calc_area(sq a) {
        float s;
        s = a->length * a->width;
        return s;
    }
    
    int main() {
        sq a;
        a->length = 10.0;
        a->width = 3.0;
    
        printf("%f\n", calc_area(a));
    }
    

    问题一: gcc area.c -o area.exe 能够编译成功,但运行时在 mac 上提示 bus error ,在 linux 上提示段错误。有朋友告诉我把sq a;改成sq a=new Square();然后用 g++编译,确实能够成功,但这样就和原来复杂的程序产生了结构性变化。原复杂程序里面的定义和我这个简单程序是一样的,但能够成功运行,不知道为什么这个简单程序就出错了。

    问题二: 如果这个简单的程序能够运行,如何将calc_area()这个函数用 Cython 封装呢?主要的难点是,这里 sq 是个结构体指针, Cython 貌似并没有能力自动处理这种非常规类型的接口。

    求各位 V 友指点!谢谢

    第 1 条附言  ·  2017-01-12 13:34:23 +08:00
    感谢 V 友指点,如下程序已经可以正常运行!还剩下关于 Cython 的问题二需要帮助。。

    #include <stdio.h>
    #include <stdlib.h>

    struct Square {
    float length;
    float width;
    };

    typedef struct Square *sq;

    float calc_square(sq a) {
    float s;
    s = a->length * a->width;
    return s;
    }

    int main() {
    sq a;
    a = malloc(sizeof(struct Square)); /*添加了这行*/
    a->length = 10.0;
    a->width = 3.0;

    printf("%f\n", calc_square(a));
    }
    8 条回复    2017-01-12 14:22:51 +08:00
    herozem
        1
    herozem  
       2017-01-12 13:09:45 +08:00   ❤️ 1
    因为,你的 c ,写错了。

    #include <stdio.h>
    #include <string.h>

    struct Square {
    float length;
    float width;
    };

    typedef struct Square *sq;

    float calc_area(const sq a) {
    float s;
    s = a->length * a->width;
    return s;
    }

    int main() {
    struct Square a;
    a.length = 10.0;
    a.width = 3.0;

    printf("%f\n", calc_area(&a));
    }
    lyricorpse
        2
    lyricorpse  
    OP
       2017-01-12 13:20:27 +08:00
    @herozem 多谢回复 但是我定义和赋值的写法都是按照那个复杂 C 程序写的。
    比如用 typedef 把 sq 指针定义成 Square 结构体后,后面就一直用 sq 了,定义时没有再 struct Square a 而是直接 sq a ;函数的参数也没有 const sq a 而是 sq a 。
    但是那个复杂程序用 gcc 编译成功,运行时也没出问题。

    我上面提到,如果把 sq a;改成 sq a=new Square(); 用 g++就能编译成功可运行,请问这个地方怎么解释呢?
    Andiry
        3
    Andiry  
       2017-01-12 13:27:21 +08:00   ❤️ 1
    sq a;
    只是声明了一个指针。指针指向的空间没有分配。
    lyricorpse
        4
    lyricorpse  
    OP
       2017-01-12 13:31:40 +08:00
    @Andiry 啊。。确实漏掉了,原复杂程序中有一段 malloc 藏在 if 里没注意。。感谢!
    MCVector
        5
    MCVector  
       2017-01-12 13:54:46 +08:00 via Android   ❤️ 1
    指针没有释放,有内存泄漏。最后还要 free(a); 而且这段程序其实没有必要用指针吧。
    lyricorpse
        6
    lyricorpse  
    OP
       2017-01-12 14:02:10 +08:00
    @MCVector 多谢提醒,这个小程序是一个很复杂的大程序的简化,我主要是想搞明白如何封装了给 Python 调用。我第一次尝试封装 C 程序,所以先写个简单的试试。
    MCVector
        7
    MCVector  
       2017-01-12 14:10:56 +08:00 via Android   ❤️ 1
    @lyricorpse 可以试试 boost Python 封装成 module 。 或者直接用 libpython 也行。之前写过一个[简单例子]( https://github.com/v3c70r/GL4Framework/blob/dev/src/app/pyConsole.cpp), 看看能不能帮到你。
    lyricorpse
        8
    lyricorpse  
    OP
       2017-01-12 14:22:51 +08:00
    @MCVector 谢谢!我试试看
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2521 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 15:30 · PVG 23:30 · LAX 07:30 · JFK 10:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.