0

SWIGを使用して不透明(OPAQUE)型をCでラップしようとしていますが、その方法がわかりません。以下に3つのファイルがあります。

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"

このCMakeLists.txtを使用して、CMakeを使用してすべてをビルドします。

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)不透明(OPAQUE)型の名前をsimplelib_MyTypeからMyTypeに変更します。2)%extendを使用してコンストラクタ/デストラクタ/メソッドで型を公開します。

問題は、上記がビルドされたpythonモジュールの型を公開しないことです。インターフェイスファイルがtypedefをtypedefed名のクラスとして公開することを期待しますが、それは起こりません。したがって、上記のポイント1と2に進むことはできません。私は何が間違っているのですか?

よろしく、リッカード

4

1 に答える 1

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、戻り値はCコードではなくPythonによって所有され、すべての参照が破棄されると解放されます。ただし、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]
于 2013-03-31T04:07:08.970 に答える