2

だから私はPythonのctypesモジュールを利用することを学んでいます。
サンプル .dll を取得するために Windows で gcc -shared (バージョン 4.8) を使用してコンパイルした単純な C ファイルを次に示します。

#include <stdio.h>
int addition(int a, int b){
    return a+b;
}

次のように Python からアクセスできるようになりました。

>>>from ctypes import *
>>>mylibc = CDLL(r"somepath\mysample.dll")
>>>mylibc.addition
<_FuncPtr object at 0x00000000031456C8>
>>>mylibc.addition(2,3)
5

今、私はこの関数を含む別の、より大きく、より複雑な .c ファイルで同じことをしようとしています:

__declspec(dllexport) void __stdcall
flopequity(HW hero[], HW villain[], double hcounters[],
double vcounters[], double hsums[], double vsums[], ulong board,
__int32 lenh, __int32 lenv)

ここで、HW は構造体の typedef です。GCC でコンパイルし、以前と同じようにその関数にアクセスできますが、__declspec(dllexport) または _ stdcall (またはその両方) を削除すると、関数にアクセスできなくなります。
私の質問は、最初の例の単純な関数にアクセスできるのに、より複雑な関数にアクセスできない理由は何でしょうか。C コードをコンパイルして ctypes からアクセスするときに、呼び出し規則/
_declspec を使用するためのルールは何ですか?

4

1 に答える 1

4

gccデフォルトで関数をエクスポートするようですが、PE Explorer (View > Export) などの任意の PE ビューアーを使用して、エクスポートされた関数を表示できます。

ここに画像の説明を入力

ただし、このコードを VC++ でコンパイルしようとすると、この関数はエクスポートされません。エクスポートされた関数がないことがわかります。

ここに画像の説明を入力

この関数をエクスポートするように依頼する必要があります。

__declspec(dllexport) int addition(int a, int b){
    return a+b;
}

呼び出し規約に関しては、ルールは単純です。

関数がほとんどの Win32API と同様に を使用する場合、またはを使用__stdcallして DLL をインポートする必要があります。例:WinDLL('mylib.dll')windll.mylib

> type mylib.c
__declspec(dllexport) int __stdcall addition(int a, int b) {
    return a+b;
}

***********************************************************************

> cl mylib.c /link /dll /out:mylib.dll
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright (C) Microsoft Corporation.  All rights reserved.

mylib.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:mylib.exe
/dll
/out:mylib.dll
mylib.obj
   Creating library mylib.lib and object mylib.exp

***********************************************************************

> python
>>> from ctypes import *
>>>
>>> WinDLL('mylib.dll').addition(1, 2)
3
>>> windll.mylib.addition(1, 2)
3
>>>

関数が を使用する場合、 witch がデフォルトの呼び出し規約であるため、またはを使用__cdeclして DLL をインポートする必要があります。例:CDLL('mylib.dll')cdll.mylib'

> type mylib.c
// `__cdecl` is not needed, since it's the default calling convention
__declspec(dllexport) int addition(int a, int b){
    return a+b;
}

***********************************************************************

> cl mylib.c /link /dll /out:mylib.dll
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright (C) Microsoft Corporation.  All rights reserved.

mylib.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:mylib.exe
/dll
/out:mylib.dll
mylib.obj
   Creating library mylib.lib and object mylib.exp

***********************************************************************

> python
>>> from ctypes import *
>>>
>>> CDLL('mylib.dll').addition(1, 2)
3
>>> cdll.mylib.addition(1, 2)
3
>>>
于 2013-08-17T02:53:40.957 に答える