如何从DLL本机调用此函数?

时间:2012-06-21 23:21:58

标签: c# visual-studio-2010 dllimport

我使用DLL导出查看器尝试查找此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();

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

3 个答案:

答案 0 :(得分:2)

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

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

您必须在C ++或C ++ / CLR中执行此操作,因为您无法在C#中创建C ++类。另请参阅Create unmanaged c++ object in c#

答案 1 :(得分:1)

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

  1. 你需要找到“真实”的名字;导出查看器显然显示了未编码的名称,但实际的C ++函数名称看起来会更加丑陋,如@0GetPartitionCount@CSTVdsDisk@@QPBAEXA或类似名称。您可能需要使用dumpbin等较低级别的工具来查找该名称。
  2. 你需要伪造“thiscall”风格的电话;这意味着您需要传递 C ++类的实例作为第一个参数。这只有在C ++类构造函数也从DLL公开时才能工作;在这种情况下,您可以调用类构造函数,将结果存储在IntPtr中,并将其传递给每个后续调用。 (如果构造函数作为DLL导出公开,则其错位名称将以??开头,如`?? 0CSTVdsDisk @@ QAE @ ABV0 @@ Z
  3. This CodeProject article向您展示了如何做到这一点,但它非常脆弱,所以期待出现问题。我强烈建议你找一个类似的非C ++库,或者至少有一个可以从C代码中使用的库。

答案 2 :(得分:0)

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

通常我定义以下宏:

#define DLLEXPORT extern "C" __declspec(dllexport)

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

 DLLEXPORT __cdecl int Example(int x, int y)

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