بيثون: الوصول إلى وظيفة DLL باستخدام CTTYPES - الوصول حسب الوظيفة * فشل الاسم *
-
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 ++ يتم تشغيله بواسطة المحول البرمجي وعدم تصديره من DLL كما RingBell
. وبعد هل راجعت أنه يظهر في الأسماء المصدرة تماما مثل هذا؟
نصائح أخرى
يعتبر برنامج التحويل البرمجي C ++ الخاص بك أسماء جميع الكائنات المرئية من الخارج للتفكير (بالإضافة إلى أسماءها الأساسية) أسماء أسماءهم والفئات والتوقيعات (هكذا يصبح التحميل الزائد ممكنا).
من أجل تجنب هذا المشحونة، تحتاج إلى extern "C"
على الأسماء المرئية من الخارج التي تريد أن تكون مرئيا من رمز غير C ++ (وبالتالي لا يمكن زيادة مثل هذه الأسماء، ولا في معيار C ++ هل يمكن أن تكون مضمنة، داخل مساحات الأسماء، أو داخل الفصول، على الرغم من أن بعض محامليات C ++ تمتد المعيار في بعض هذه الاتجاهات).
كل شيء يعمل الآن :) لتلخيص مشاركاتك:
اكتب DLL في C ++:
// 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