在foo.dll中给定以下C++类:
class a{
private:
int _answer;
public:
a(int answer) { _answer = answer; }
__declspec(dllexport) int GetAnswer() { return _answer; }
}
我希望能够从C#中调用pInvoke GetAnswer方法。为此,我使用以下方法:
[DllImport("foo.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint= "something")]
public static extern int GetAnswer(IntPtr thisA);
我传入了一个指向a的IntPtr(它来自其他地方,但不重要)。
CallingConvention = CallingConvention.ThisCall
确保它会被正确处理。这个问题很棒的一点是,我知道到目前为止我是对的,因为它已经非常好地运作了!使用Depends.exe,我可以看到 "GetAnswer" 被导出为 ?GetAnswer@a@@UAEHXZ(或者是类似的东西——重点是它已经被名称缩短了)。当我将缩短的名称插入 EntryPoint 的“something”中时,一切都很好!在想到使用Depends.exe之前,我花了大约一天的时间,所以我会把它留在这里,帮助任何遇到类似问题的人。
我的真正问题是:有没有办法禁用 GetAnswer 的 C++ 名称缩短,以便我不需要将缩短后的名称作为我的 entry point。因为我的理解是名称缩短可能会因编译器变化而发生改变,所以在其中放置缩短后的名称似乎会引发问题。此外,对于我想要 pInvoke 的每个实例方法都使用 Depends.exe 是一件麻烦的事情。
编辑:忘记添加我尝试过的内容了: 我似乎无法在函数声明上放置 extern "C",尽管我可以将其放置在定义中。这似乎没有帮助(当你想到它时是显而易见的)。
我能想到的唯一其他解决方案是创建一个包装实例方法并将 a 的实例作为参数传递的 C 风格函数。然后,在该包装器上禁用名称缩短,并 pInvoke 该函数。不过,我宁愿坚持我已经拥有的解决方案。我已经告诉我的同事们 pInvoke 很棒。如果我不得不在我们的 C++ 库中添加特殊函数来使 pInvoke 工作,那我会看起来很傻的。
dumpbin /exports foo.dll
和链接器的 .map 文件。请注意,您无法使用 PInvoke 调用此函数,需要使用 C++/CLI 包装器。 - Hans Passant