Frage

myPythonClient (unten) will eine ringBell Funktion (aus einer DLL mit ctypes geladen) aufzurufen. Allerdings versucht ringBell über seine Name für den Zugriff Ergebnisse in einem AttributeError. Warum?

RingBell.h enthält

namespace MyNamespace
    {
    class MyClass
        {
        public:
            static __declspec(dllexport) int ringBell ( void ) ;
        } ;
    }

RingBell.cpp enthält

#include <iostream>
#include "RingBell.h"
namespace MyNamespace
    {
    int __cdecl MyClass::ringBell ( void )
        {
        std::cout << "\a" ;
        return 0 ;
        }
    }

myPythonClient.py enthält

from ctypes import *
cdll.RingBell[1]() # this invocation works fine
cdll.RingBell.ringBell() # however, this invocation errors out
# AttributeError: function 'ringBell' not found
War es hilfreich?

Lösung

Vielleicht, weil der C ++ Name wird vom Compiler verstümmelt und nicht aus der DLL als RingBell exportiert. Haben Sie überprüft, dass es in den exportierten Namen genau so angezeigt wird?

Andere Tipps

Ihre C ++ Compiler ist Mangeln der Namen aller von außen sichtbaren Objekten zu reflektieren (sowie die zugrunde liegenden Namen) ihre Namespaces, Klassen und Unterschriften (das ist, wie Überlastung möglich wird).

Um diese Mangeln zu vermeiden, benötigen Sie einen extern "C" auf äußerlich sichtbare Namen, die Sie sichtbar von Nicht-C ++ Code sein soll (und daher solche Namen nicht überlastet werden, noch in C ++ Standard können sie inline sein, innerhalb von Namespaces, oder innerhalb von Klassen, obwohl einige C ++ Compiler den Standard in einigen dieser Richtungen erstrecken).

Alles funktioniert jetzt :) Ihre Beiträge Fassen wir zusammen:

Write DLL in 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;
} 

Dann können Sie Programm link.exe verwenden, um echte Funktionsnamen in dll zu sehen. link.exe ist zum Beispiel in MSVC2010 hier:

c:\program files\microsoft visual studio 10.0\VC\bin\link.exe

Verwendung:

link /dump /exports yourFileName.dll

Sie sehen etwas wie:

ordinal hint RVA      name
      1    0 00001040 ?MyAdd2@@YAHHH@Z = ?MyAdd2@@YAHHH@Z (int __cdecl MyAdd2(int,int))
      2    1 00001030 MyAdd = _MyAdd

Dann in Python Sie können es als importieren:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top