我已经构建了一个C ++ dll,我想用C#代码调用它。我可以调用一个函数,但是当C#代码尝试加载dll时,另一个函数会抛出异常。
标题如下所示:
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
这会产生一个带有轻微混乱的导出表的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
我的P / Invoke声明如下所示:
[DllImport("PPPManager.dll")]
private static extern bool Install();
[DllImport("PPPManager.dll")]
private static extern bool PPPConnect();
对Install的调用没有异常返回,但是当我调用PPPConnect时,我得到一个MissingMethodException - “在PInvoke DLL'PPPManager.dll'中找不到入口点'PPPConnect'。”
我已尝试从Install函数声明中删除extern和declspec指令,因此PPPConnect是唯一导出的函数,这仍然不允许我调用PPPConnect。
我也试过按顺序做DllImport;这给出了与按名称调用相同的结果 - 安装返回,但PPPConnect抛出异常“无法找到入口点'#2'......”。
互操作日志给出:
[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();
这远远超出我的专业领域,所以欢迎任何建议或想法。
谢谢, 保罗
编辑: 事实证明这个代码确实有效;问题是最新的DLL没有传播到设备。 D'哦!
答案 0 :(得分:8)
您是否在dll项目中使用.def文件导出这些功能?如果是这样,请将其删除并重试。这只是一个猜测,因为当你做一个extern“C”declspec(dllexports)时,看起来你的出口不是它们应该是的。
我使用
使用简单的C ++ dll尝试了这一点extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
和一个使用PInvoke声明的简单C#应用程序,它运行正常。
当我在dll上执行dumpbin / exports时,我看到了:
转储文件PPPManager.dll
文件类型: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)
请注意,导出的名称在我的情况下是不同的。
答案 1 :(得分:1)
它可能像PPPConnect
那样简单,但却被操作系统误解为错误。尝试将Install
和PPPConnect
同时作为no-ops实现(只需让它们返回TRUE
而不做任何其他操作)并查看错误是否仍然存在。如果是这样,请尝试交换它们的导出顺序(仍然是无操作)并查看问题是否与排序(不太可能)或其他相关联。
您还可以使用图形工具depends
来确认DLL的导出表是什么样的,但我怀疑问题是来自这些区域。
答案 2 :(得分:1)
根据您的描述,安装和PPPConnect仅在名称上有所不同。我想你只需在你的C#应用程序中使用旧的.dll版本。没有定义PPPConnect的那个。
声明看起来是正确的(据我所知,没有来源)。
答案 3 :(得分:0)
很棒的信息,但正如你所说,一切都在这里。尝试安装Windows调试工具并运行:
kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*"
获得更好的符号表转储;这也是一个盲目的镜头,但你也可以尝试:
extern "C"
{
__declspec(dllexport) BOOL Install();
__declspec(dllexport) BOOL PPPConnect();
};
如果__declspec正在做一些奇怪的事情。
答案 4 :(得分:0)
使用依赖性walker并打开DLL来验证可用的方法