将函数从 C++ dll 导出到 C# P/Invoke
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/571799/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Exporting functions from C++ dll to C# P/Invoke
提问by Symmetric
I have built a C++ dll that I would like to call from C# code. I'm able to call one function, but the other throws an exception when the C# code tries to load the dll.
我已经构建了一个 C++ dll,我想从 C# 代码中调用它。我可以调用一个函数,但是当 C# 代码尝试加载 dll 时,另一个函数会引发异常。
The header looks like this:
标题如下所示:
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
This produces a dll with slightly confusing exports table (what does foo = foo mean in the name field?):
这会生成一个带有稍微令人困惑的导出表的 dll(名称字段中的 foo = foo 是什么意思?):
File Type: DLL
Section contains the following exports for PPPManager.dll
00000000 characteristics
499F44F0 time date stamp Fri Feb 20 16:04:00 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 000078E4 Install = Install
2 1 000079DC PPPConnect = PPPConnect
My P/Invoke declarations look like this:
我的 P/Invoke 声明如下所示:
[DllImport("PPPManager.dll")]
private static extern bool Install();
[DllImport("PPPManager.dll")]
private static extern bool PPPConnect();
The call to Install returns with no exception, but when I call PPPConnect, I get a MissingMethodException - "Can't find an Entry Point 'PPPConnect' in a PInvoke DLL 'PPPManager.dll'."
对安装的调用无一例外地返回,但是当我调用 PPPConnect 时,我得到一个 MissingMethodException - “在 PInvoke DLL 'PPPManager.dll' 中找不到入口点 'PPPConnect'。”
I've tried removing the extern and declspec directives from the Install function declaration, so that PPPConnect is the only function exported, and this still doesn't let me call PPPConnect.
我已经尝试从 Install 函数声明中删除 extern 和 declspec 指令,以便 PPPConnect 是唯一导出的函数,但这仍然不允许我调用 PPPConnect。
I have also tried doing the DllImport by ordinal; this gives the same result as calling by name - Install returns, but PPPConnect throws the exception "Can't find an Entry Point '#2'...".
我也尝试过按顺序执行 DllImport;这给出了与按名称调用相同的结果 - 安装返回,但 PPPConnect 抛出异常“找不到入口点 '#2'...”。
The interop log gives:
互操作日志给出:
[pinvokeimpl][preservesig]
bool invivodata.Common.System.IPAQUtils::Install();
BOOLEAN (I1_WINBOOL_VAL) Install();
JIT ERROR FOR PINVOKE METHOD (Managed -> Native):
[pinvokeimpl][preservesig]
bool invivodata.Common.System.IPAQUtils::PPPConnect();
BOOLEAN (I1_WINBOOL_VAL) PPPConnect();
This is well outside my area of expertise, so any suggestions or thoughts would be welcome.
这完全超出了我的专业领域,因此欢迎提出任何建议或想法。
Thanks, Paul
谢谢,保罗
edit: It turns out that this code does work; the problem was with the latest dll not being propagated to the device. D'oh!
编辑:事实证明这段代码确实有效;问题在于最新的 dll 没有传播到设备。哦!
采纳答案by m-sharp
Are you using a .def file in your dll project to export those functions? If so, remove it and try again. This is just a guess because it looks like your exports are not what they should be when you do an extern "C" declspec(dllexports).
您是否在 dll 项目中使用 .def 文件来导出这些函数?如果是这样,请将其删除并重试。这只是一个猜测,因为当您执行 extern "C" declspec(dllexports) 时,您的导出看起来不像它们应该是的样子。
I tried this out with a simple C++ dll using
我用一个简单的 C++ dll 尝试了这个
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
and a simple C# app using your PInvoke declarations and it worked fine.
和一个使用 PInvoke 声明的简单 C# 应用程序,它运行良好。
When I did a dumpbin/exports on the dll I saw:
当我对 dll 执行转储/导出时,我看到:
Dump of file PPPManager.dll
文件 PPPManager.dll 的转储
File Type: DLL
文件类型:DLL
Section contains the following exports for PPPManager.dll
部分包含以下 PPPManager.dll 导出
00000000 characteristics
499F6C2D time date stamp Fri Feb 20 20:51:25 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 000110CD Install = @ILT+200(_Install)
2 1 00011069 PPPConnect = @ILT+100(_PPPConnect)
Notice that the exported names are different in my case.
请注意,导出的名称在我的情况下是不同的。
回答by Ana Betts
Great information, but as you mention, everything is in order here. Try installing Debugging Tools for Windows and running:
很好的信息,但正如你所提到的,这里一切都井井有条。尝试安装 Windows 调试工具并运行:
kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*"
to get a better dump of the symbols table; it's a blind shot as well, but you could also try:
获得更好的符号表转储;这也是一个盲目的镜头,但你也可以尝试:
extern "C"
{
__declspec(dllexport) BOOL Install();
__declspec(dllexport) BOOL PPPConnect();
};
in case the __declspec is doing something weird.
以防 __declspec 做一些奇怪的事情。
回答by vladr
It could be something as simple as PPPConnect
failing in a way that gets misinterpreted by the OS. Try implementing both Install
and PPPConnect
as no-ops (just have them return TRUE
without doing anything else) and see if the error persists. If so, try swapping the order in which they are exported (still as no-ops) and see if the problem is tied to ordering (unlikely) or to something else.
它可能像PPPConnect
以被操作系统误解的方式失败一样简单。尝试同时实现Install
和PPPConnect
作为无操作(只让它们返回TRUE
而不做任何其他事情)并查看错误是否仍然存在。如果是这样,请尝试交换导出它们的顺序(仍为无操作),看看问题是否与排序(不太可能)或其他问题有关。
You can also use the graphical tool depends
to confirm what the DLL's exports table looks like, but I doubt the problem is coming from those quarters.
您还可以使用图形工具depends
来确认 DLL 的导出表是什么样的,但我怀疑问题出在这些方面。
回答by alex2k8
According to your description Install and PPPConnect differs only in names. I guess you simply use old .dll version with your C# application. A one without PPPConnect defined.
根据您的描述,Install 和 PPPConnect 仅在名称上有所不同。我猜你只是在你的 C# 应用程序中使用旧的 .dll 版本。一个没有定义 PPPConnect 的。
The declarations looks right (as far as I can judge without sources).
声明看起来是正确的(据我所知,没有消息来源)。
回答by patrick
use dependency walker and open your DLL to verify what methods are available
使用依赖遍历器并打开您的 DLL 以验证可用的方法