8

我已经构建了一个我想从 C# 代码调用的 C++ dll。我可以调用一个函数,但是当 C# 代码尝试加载 dll 时,另一个会引发异常。

标题如下所示:

extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();

这会生成一个带有稍微混乱的导出表的 dll(foo = foo 在 name 字段中是什么意思?):

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 没有传播到设备。哦!

4

5 回答 5

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)

请注意,在我的情况下,导出的名称是不同的。

于 2009-02-21T02:51:05.707 回答
1

它可能很简单,比如PPPConnect以一种被操作系统误解的方式失败。尝试同时实现InstallPPPConnect作为无操作(只是让它们返回TRUE而不做任何其他事情)并查看错误是否仍然存在。如果是这样,请尝试交换它们的导出顺序(仍然是无操作),看看问题是否与排序有关(不太可能)或其他原因。

您还可以使用图形工具depends来确认 DLL 的导出表是什么样的,但我怀疑问题出在那些方面。

于 2009-02-21T02:00:18.027 回答
1

根据您的描述,Install 和 PPPConnect 仅在名称上有所不同。我猜你只是在你的 C# 应用程序中使用旧的 .dll 版本。一个没有定义 PPPConnect。

声明看起来是正确的(据我所知,没有消息来源)。

于 2009-02-21T02:12:17.483 回答
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 做一些奇怪的事情。

于 2009-02-21T01:59:04.753 回答
0

使用依赖遍历器并打开您的 DLL 以验证可用的方法

于 2009-03-27T15:02:06.803 回答