9

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
4

3 に答える 3

11

C ++コンパイラは、外部から表示されるすべてのオブジェクトの名前を操作して、それらの名前空間、クラス、および署名を反映します(これにより、オーバーロードが可能になります)。

このマングリングを回避するには、extern "C"C ++以外のコードから表示したい外部から表示される名前が必要です(したがって、このような名前はオーバーロードできません。また、C ++標準では、インライン、名前空間内、またはクラス内で使用できます。ただし、一部のC ++コンパイラは、これらの方向のいくつかで標準を拡張します)。

于 2009-07-06T17:13:35.223 に答える
10

すべてが現在機能しています:)投稿を要約するには:

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

次に、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
于 2011-12-12T12:02:01.130 に答える
7

おそらく、C ++名がコンパイラによって変更され、DLLからとしてエクスポートされないためRingBellです。エクスポートされた名前にそのように表示されることを確認しましたか?

于 2009-07-06T17:08:32.817 に答える