بيثون: الوصول إلى وظيفة DLL باستخدام CTTYPES - الوصول حسب الوظيفة * فشل الاسم *

StackOverflow https://stackoverflow.com/questions/1088085

سؤال

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top