Pythonの:ctypesのを使用してDLL関数にアクセスする - 機能*名によるアクセス*失敗
-
23-08-2019 - |
質問
myPythonClient
(下)(ringBell
を使用してDLLからロード)ctypes
関数を呼び出したいです。しかし、ringBell
にそのの名前の結果を経由してAttributeError
にアクセスしようとしています。なぜ?
RingBell.h
が含まれています。
namespace MyNamespace
{
class MyClass
{
public:
static __declspec(dllexport) int ringBell ( void ) ;
} ;
}
RingBell.cpp
が含まれています。
#include <iostream>
#include "RingBell.h"
namespace MyNamespace
{
int __cdecl MyClass::ringBell ( void )
{
std::cout << "\a" ;
return 0 ;
}
}
myPythonClient.py
が含まれています。
from ctypes import *
cdll.RingBell[1]() # this invocation works fine
cdll.RingBell.ringBell() # however, this invocation errors out
# AttributeError: function 'ringBell' not found
解決
おそらく、C ++の名前は、コンパイラによって壊さとRingBell
としてDLLからエクスポートされていないため。あなたはそれがまさにそのようなエクスポートされた名前で表示されていることを確認しましたか?
他のヒント
あなたのC ++コンパイラは、(それが可能になる方法をオーバーロードです)を反映するために、すべての外部から見えるオブジェクトの名前をマングリング(並びにその基礎となる名前)自分の名前空間、クラス、および署名されます。
このマングリングを避けるために、あなたは非C ++コードから(したがって、このような名前が過負荷にすることはできません見えるようにしたい外部から見える名前のextern "C"
を必要とし、またC ++標準では、彼らはインラインすることができ、名前空間内で、またはクラス、いくつかのC ++コンパイラは、これらの方向のいくつかの標準を拡張するが)内
すべてはあなたの記事を要約すると:)今取り組んでいる。
C ++でDLLを書くます:
// Header
extern "C"
{ // Name in DLL will be "MyAdd" - but you won't be able to find parameters etc...
__declspec(dllexport) int MyAdd(int a, int b);
}
// Name will be with lot of prefixes but some other info is provided - IMHO better approach
__declspec(dllexport) int MyAdd2(int a, int b);
//.cpp Code
__declspec(dllexport) int MyAdd(int a, int b)
{ return a+b;
}
__declspec(dllexport) int MyAdd2(int a, int b)
{ return a+b;
}
次に、あなたは、DLL内の実際の関数名を確認するために、プログラムLINK.EXEを使用することができます。 LINK.EXEはここMSVC2010、例えば次のとおりです。
c:\program files\microsoft visual studio 10.0\VC\bin\link.exe
使用:
link /dump /exports yourFileName.dll
あなたのような何かを参照してください。
ordinal hint RVA name
1 0 00001040 ?MyAdd2@@YAHHH@Z = ?MyAdd2@@YAHHH@Z (int __cdecl MyAdd2(int,int))
2 1 00001030 MyAdd = _MyAdd
次に、Pythonであなたのようにそれをインポートすることができます:
import ctypes
mc = ctypes.CDLL('C:\\testDll3.dll')
#mc.MyAdd2(1,2) # this Won't Work - name is different in dll
myAdd2 = getattr(mc,"?MyAdd2@@YAHHH@Z") #to find name use: link.exe /dump /exports fileName.dll
print myAdd2(1,2)
#p1 = ctypes.c_int (1) #use rather c types
print mc[1](2,3) # use indexing - can be provided using link.exe
print mc.MyAdd(4,5)
print mc[2](6,7) # use indexing - can be provided using link.exe