Python : CTypes를 사용하여 DLL 기능 액세스 - 기능 별 액세스 * 이름 * 실패
-
23-08-2019 - |
문제
myPythonClient
(아래) a 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 ++ 이름이 컴파일러에 의해 엉망이되고 DLL에서 다음과 같이 내보내지 않기 때문일 수 있습니다. RingBell
. 내보낸 이름으로 정확히 같은 이름으로 표시되었는지 확인 했습니까?
다른 팁
C ++ 컴파일러는 네임 스페이스, 클래스 및 서명 (과부하가 가능한 방법)을 반영하기 위해 외부가 보이는 모든 개체의 이름을 관리합니다 (기본 이름뿐만 아니라 기본 이름뿐만 아니라).
이 엉망인을 피하려면 extern "C"
비 C ++ 코드에서 볼 수 있도록 외부 가시적 인 이름에서 (따라서 일부 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;
}
그런 다음 프로그램 link.exe를 사용하여 DLL에서 실제 기능 이름을 볼 수 있습니다. 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
그런 다음 파이썬에서는 다음과 같이 가져올 수 있습니다.
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
제휴하지 않습니다 StackOverflow