9

C++ には標準の ABI がないことをよく知っているので、次のようにしました。

//trialDLL.h
#ifndef TRIALDLL_H_
#define TRIALDLL_H_

class MyMathFuncs
{
private:
    double offset;

public:
    MyMathFuncs(double offset);

    ~MyMathFuncs();

    double Add(double a, double b);

    double Multiply(double a, double b);

    double getOffset();
};

#ifdef __cplusplus
extern "C"{
#endif

#ifdef TRIALDLL_EXPORT
#define TRIALDLL_API __declspec(dllexport)
#else
#define TRIALDLL_API __declspec(dllimport)
#endif

    TRIALDLL_API MyMathFuncs* __stdcall new_MyMathFuncs(double offset);

    TRIALDLL_API void __stdcall del_MyMathFuncs(MyMathFuncs *myMath);

    TRIALDLL_API double __stdcall MyAdd(MyMathFuncs* myMath, double a, double b);


#ifdef __cplusplus
}
#endif

#endif

そして定義 .cpp: (他のクラス関数の定義は省略されています)

//trialDLL.cpp
#include "trialDLL.h"

MyMathFuncs* __stdcall new_MyMathFuncs(double offset)
{
return new MyMathFuncs(offset);
}


void __stdcall del_MyMathFuncs(MyMathFuncs *myMath)
{
    myMath->~MyMathFuncs();
}


double __stdcall MyAdd(MyMathFuncs *myMath, double a, double b)
{
return myMath->Add(a, b);
}

// class functions
double MyMathFuncs::Add(double a, double b)
{
return a+b+ this->offset;
}

これを dll にビルドし、trialDLL3.dll という名前を付けました。次に、Pythonで、モジュールを次のように記述しました。

#trialDLL3.py
import ctypes
from ctypes import WinDLL

class MyMath(object):
    def __init__(self, offset):
        self.FunMath = WinDLL('trialDLL3.dll')
        self.FunMath.new_MyMathFuncs.argtypes = [ctypes.c_double]
        self.FunMath.new_MyMathFuncs.restype = ctypes.c_void_p

        self.FunMath.MyAdd.argtypes = [ctypes.c_void_p, \
                                       ctypes.c_double, ctypes.c_double]
        self.FunMath.MyAdd.restype = ctypes.c_double

        self.obj = self.FunMath.new_MyMathFuncs(offset)

    def FunAdd(self, a, b):
        self.FunMath.MyAdd(self.obj, a, b)

    def delete(): 
        self.FunMath.del_MyMathFuncs()

これらすべての後、奇妙なことが起こりました。IDLE python シェルでは、次のことを行いました。

theMath = MyMath(3.3)        #create the instance
theMath.FunAdd(3.3, 3.3)     #call the function

2 行目は 9.9 ではなく None を返しました。次に、次の行をシェルに追加して、別の方法を試しました。

theMath.FunMath.MyAdd(theMath.obj, 3.3 ,3.3)

そして、この行は当然のことながら 9.9 を返しますが、最後の結果 None と比較すると驚くべきことです。これらの 2 つの行は同一であるべきではありませんか? そして、これらすべての行を Python シェルで明示的に実行し、何がうまくいかないかを確認することにしました: (インポートを除く)

loadedDLL = WinDLL('trialDLL3.dll')
loadedDLL.new_MyMathFuncs.argtypes = [ctypes.c_double]
loadedDLL.new_MyMathFuncs.restype = ctypes.c_void_p
loadedDLL.MyAdd.argtypes = [ctypes.c_void_p, \
                                    ctypes.c_double, ctypes.c_double]
loadedDLL.MyAdd.restype = ctypes.c_double
obj = loadedDLL.new_MyMathFuncs(3.3)
FunMath.MyAdd(obj, 3.3, 3.3)

これらすべての行は、最終的に 9.9 を返しました。これらの行は、trialDLL3.py モジュールがインポートされた場合の 2 つの行と同じではありませんか?

theMath = MyMath(3.3)        #create the instance
theMath.FunAdd(3.3, 3.3)     #call the function

それらが同じ取引である場合、2 行のクラス バージョンが None を返し、明示的な方法が期待される 9.9 を返すのはなぜですか? 前もって感謝します!

4

1 に答える 1

5

すべて正常に動作します...しかし、メソッド MyMath.FunAdd で C 関数の戻り値を渡すのを忘れていました!

def FunAdd(self, a, b):
    return self.FunMath.MyAdd(self.obj, a, b)
    ^^^^^^
于 2013-04-28T22:16:22.477 に答える