【问题标题】:Expose an opaque type to python using swig使用 swig 向 python 公开不透明类型
【发布时间】:2013-03-27 11:15:46
【问题描述】:

我正在尝试使用 SWIG 在 C 中包装一个不透明类型,但我不明白如何去做。我在下面列出了三个文件:

simplelib.c:

#include <assert.h>
#include <stdlib.h>
#include "simplelib.h"

struct _simplelib_my_type {
    double x;
    double y;
};

simplelib_MyType *
simplelib_mytype_create(double x, double y)
{
    simplelib_MyType *mt = NULL;
    if (mt = calloc(1, sizeof(*mt))) {
        mt->x;
        mt->y;
    }
    return mt;
}

void
simplelib_mytype_destroy(simplelib_MyType *mt)
{
    if (mt) {
        free(mt);
        mt = NULL;
    }
}

int
simplelib_mytype_calc(const simplelib_MyType *mt, double z, double *res)
{
    int ok = 0;
    assert(mt);
    if (z != 0.0) {
        *res = mt->x * mt->y / z;
        ok = 1;
    }
    return ok;
}

simplelib.h:

#ifndef SIMPLELIB_H
#define SIMPLELIB_H

typedef struct _simplelib_my_type simplelib_MyType;

simplelib_MyType *simplelib_mytype_create(double x, double y);
void simplelib_mytype_destroy(simplelib_MyType *mt);

int simplelib_mytype_calc(const simplelib_MyType *mt, double z, double *res);

#endif // SIMPLELIB_H

还有我的接口文件 simplelibswig.i:

%module simplelibswig
%{
    extern "C" {
        #include "simplelib.h"
    }
%}

%include "simplelib.h"

我使用 CMake 构建一切,使用这个 CMakeLists.txt:

project(simplelib)
cmake_minimum_required(VERSION 2.8)

find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})

find_package(PythonLibs)
include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES(simplelibswig.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(simplelibswig.i PROPERTIES SWIG_FLAGS "-includeall")


add_library(${PROJECT_NAME}
    simplelib.h
    simplelib.c
)

swig_add_module(simplelibswig python simplelibswig.i)
swig_link_libraries(simplelibswig ${PYTHON_LIBRARIES} ${PROJECT_NAME})

现在,我想做的是 1) 将不透明类型从 simplelib_MyType 重命名为 MyType 2) 使用 %extend

使用构造函数/析构函数/方法公开类型

问题是上面没有暴露构建的python模块中的类型。我希望接口文件将 typedef 公开为具有 typedefed 名称的类,但这并没有发生。因此,我无法继续讨论上面的第 1 点和第 2 点。我做错了什么?

最好的问候, 里卡德

【问题讨论】:

    标签: python c swig opaque-pointers


    【解决方案1】:

    Swig 需要为您的 opaque 类型定义一个定义,以允许它被公开和扩展。即使是不准确的也可以:

    %module simplelibswig
    %{
        extern "C" {
            struct _simplelib_my_type { int _unused; };
            #include "simplelib.h"
        }
    %}
    
    struct _simplelib_my_type { int _unused; };
    %include "simplelib.h"
    

    为了让 SWIG 也管理不透明对象的内存,创建和销毁它们的函数应标记为:

    %newobject simplelib_mytype_create;
    %delobject simplelib_mytype_destroy;
    %include "simplelib.h"
    

    现在,如果 Python 代码调用 simplelib_mytype_create,则返回值将归 Python 而不是 C 代码所有,并且在所有引用被销毁时将被释放。但是如果调用simplelib_mytype_destroy 函数,Python 会知道该对象已经被释放并且不会再次释放它。

    您现在也可以使用%extend%rename 类型:

    %module simplelibswig
    %{
        struct _simplelib_my_type { int _unused; };
        #include "simplelib.h"
    %}
    
    %rename(opaque) _simplelib_my_type;
    
    struct _simplelib_my_type { int _unused; };
    %newobject simplelib_mytype_create;
    %delobject simplelib_mytype_destroy;
    %include "simplelib.h"
    
    %extend _simplelib_my_type {
        _simplelib_my_type(double a,double b) { return simplelib_mytype_create(a,b); }
        %apply double *OUTPUT { double* res };
        int calc(double z, double *res) { return simplelib_mytype_calc($self,z,res); }
        ~_simplelib_my_type() { simplelib_mytype_destroy($self); }
    }
    

    输出

    >>> import simplelibswig
    >>> simplelibswig.opaque(1.2,3.4)
    <simplelibswig.opaque; proxy of <Swig Object of type 'simplelib_MyType *' at 0x0000000002872DE0> >
    >>> a=simplelibswig.opaque(1.2,3.4)
    >>> a.calc(3.4)
    [1, 1.2]
    >>> a.calc(1.2)
    [1, 3.4000000000000004]
    

    【讨论】:

    • 非常感谢您的详细解答! SWIG 绝对非常好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多