0

我已经使用 DLL Export viewer 尝试查找此 DLL 中的函数,我找到了一个函数列表,它是:

public: int __thiscall CSTVdsDisk::GetPartitionCount(void);

问题在 C# 中,我无法使用以下任何一种方法调用该函数:

[DllImport("Some.dll", 
           ExactSpelling = true,
           EntryPoint = "GetPartitionCount",
           CallingConvention = CallingConvention.StdCall,
           SetLastError = true)]

或者:

[DllImport("Some.dll", 
           ExactSpelling = true,
           EntryPoint = "CSTVdsDisk::GetPartitionCount",
           CallingConvention = CallingConvention.StdCall,
           SetLastError = true)]
private static extern int GetPartitionSize();

他们都失败了。有什么我做错了吗?任何人都可以帮忙吗?谢谢!

4

3 回答 3

2

您不能使用 P/Invoke 调用该函数。__thiscall调用引用意味着这个函数是一个类成员函数。它是CSTVdsDisk类的成员函数。

为了能够调用该函数,您必须创建CSTVdsDisk该类的一个实例并GetPartitionCount从该实例调用。

您必须在 C++ 或 C++/CLR 中执行此操作,因为您无法在 C# 中创建 C++ 类。另请参阅在 c# 中创建非托管 c++ 对象

于 2012-06-21T23:47:13.787 回答
1

根据名称,这似乎是一个 C++ 类方法。这将使直接从 P/Invoke 调用该方法变得非常困难,原因有两个:

  1. 你需要找到“真实”的名字;导出查看器显然显示了未修改的名称,但实际的 C++ 函数名称看起来更难看,类似@0GetPartitionCount@CSTVdsDisk@@QPBAEXA或类似。您可能需要使用较低级别的工具dumpbin来查找该名称。
  2. 你需要伪造“thiscall”风格的调用;这意味着您需要将C++ 类的实例作为第一个参数传递。这只有在 C++ 类构造函数也从 DLL 中公开时才会起作用;在这种情况下,您可以调用类构造函数,将结果存储在 IntPtr 中,并将其传递给每个后续调用。(如果构造函数以 DLL 导出的形式公开,则其损坏的名称将以??`??0CSTVdsDisk@@QAE@ABV0@@Z 开头

这篇 CodeProject 文章向您展示了如何完成大部分工作,但它非常脆弱,所以预计会出现问题。我强烈建议你寻找一个做类似事情的非 C++ 库,或者至少一个设计为可从 C 代码中使用的库。

于 2012-06-21T23:52:17.510 回答
0

在您的本机代码中,确保您正在导出该函数。默认情况下,您的函数不会列在 Exports 表中,因此您需要对其进行标记,以便编译器知道导出它。您还需要将该函数标记为 extern "C",以便编译器不会破坏名称。

通常我定义以下宏:

#define DLLEXPORT extern "C" __declspec(dllexport)

处理所有这些,然后简单地声明导出的函数,例如:

 DLLEXPORT __cdecl int Example(int x, int y)

如果您发现名称仍然存在问题,请尝试在 dll 上使用免费的 PE 资源管理器程序并检查导出的函数表以获取正确的名称。

于 2012-06-21T23:32:26.477 回答