在C#中使用Delphi 7中编译的DLL

我需要在我的C#应用​​程序中使用Delphi 7中的DLL(硬件ID提取器)。

此DLL导出的函数是:

导出function:

// CPU function GetCPUSpeed: Double; function CPUFamily: ShortString; { Get cpu identifier from the windows registry } function GetCpuTheoreticSpeed: Integer; { Get cpu speed (in MHz) } function IsCPUIDAvailable: Boolean; Register; function GetCPUID (CpuCore: byte): ShortString; Function GetCPUVendor: ShortString; // RAM function MemoryStatus (MemType: Integer): cardinal; { in Bytes } function MemoryStatus_MB (MemType: Integer): ShortString; { in MB } // HDD function GetPartitionID (Partition : PChar): ShortString; { Get the ID of the specified patition. Example of parameter: 'C:' } function GetIDESerialNumber(DriveNumber: Byte ): PChar; { DriveNr is from 0 to 4 } 

我知道(显然)Delphi中的字符串不是以null结尾并且是字节(ASCII)。 但我不知道如何将这些Delphi字符串映射到C#。

谢谢。

以下是如何在C#中声明GetCPUSpeed函数的示例:

 class Program { [DllImport("the_name_of_the_delphi_library.dll")] public static extern double GetCPUSpeed(); static void Main(string[] args) { double cpuSpeed = GetCPUSpeed(); Console.WriteLine("CPU speed: {0}", cpuSpeed); } } 

还有其他可以尝试的声明:

 [DllImport("the_name_of_the_delphi_library.dll")] public static extern string CPUFamily(); [DllImport("the_name_of_the_delphi_library.dll")] public static extern int GetCpuTheoreticSpeed(); [DllImport("the_name_of_the_delphi_library.dll")] public static extern bool IsCPUIDAvailable(); [DllImport("the_name_of_the_delphi_library.dll")] public static extern string GetCPUID(byte cpuCore); [DllImport("the_name_of_the_delphi_library.dll")] public static extern string GetCPUVendor(); [DllImport("the_name_of_the_delphi_library.dll")] public static extern uint MemoryStatus(int memType); [DllImport("the_name_of_the_delphi_library.dll")] public static extern string MemoryStatus_MB(int memType); [DllImport("the_name_of_the_delphi_library.dll")] public static extern string GetPartitionID(char partition); [DllImport("the_name_of_the_delphi_library.dll")] public static extern string GetIDESerialNumber(byte driveNumber); 

问题来自您设计导出function的方式。 DLL(除其他外)是一种机制,用于以可以从以不同编程语言编写的应用程序(或其他DLL)使用的方式提供代码。

看看Windows API,有很多函数返回文本。 不幸的是,这是以很多不同的方式完成的,Windows API没有真正的标准。 但是,我很确定你不会找到一个以你的方式返回“字符串”(Pascal或C(以null结尾)字符串)的函数。 原因很简单:这会使不同的模块使用不同的编程语言变得非常困难甚至不可能。 你的DLL会为字符串分配内存,一旦调用者完成字符串,就需要释放内存。 因此,两个模块都需要共享这片内存的管理器。 C#程序如何使用你的DLL,看到他们使用完全不同的内存管理器?

从DLL获取字符串值的习惯方法是使用预分配缓冲区和参数中的缓冲区长度调用函数,让函数使用字符串内容填充该缓冲区,并让函数结果表示成功或失败。 例如,传递大小不足的缓冲区将是失败的一个原因。 不同的Windows API函数以不同的方式处理这个问题,最简单的方法可能是用常量定义最大字符串长度,例如类似于MAX_PATH

要解决您的问题,您应该使用一个知道如何从C#调用的Windows API函数,并在缓冲区中返回字符串结果,作为示例。 在此示例之后为导出的函数建模,并且应该很容易从C#程序中调用它们。

编辑:

我记得我曾经看过一个类似的问题( 如何从Delphi中制作的DLL中导入一个函数? ),现在我看起来我发现它也是你的。

您之后写道,您没有该DLL的源代码,因此更改导出的函数是不可能的。 你可以做的是在Delphi中创建一个包装DLL(或COM对象),调用原始的HardwareIDExtractor.dll并在其上提供一个理智的API。 这将允许您同时提供导出函数的AnsiChar和WideChar版本。

如果你想减少混乱(两个必要的DLL而不是一个),你也可以将原始的HardwareIDExtractor.dll作为资源放入你的包装DLL中,如本博客文章中所述: 在Delphi程序中使用存储为Resources的DLL

如果您有D7 dll的源,则可以更改导出的函数以使ShortString函数返回PChar。 您可以创建调用原始函数并进行类型转换的新函数 – 这是最简单的路径。 如果遵循此路径,则对Integer和Cardinal类型执行相同操作(分别将它们转换为LongInt和LongWord)。 下面的一些代码(我想像豪斯拉登先生这样的法师有一个更优雅的方法,但这有效:-))

 var SInput: ShortString; POutput: PAnsiChar; Tam: Integer; pt: Pointer; begin SInput := 'Alphabet'; //ShortString pt := @SInput[1]; // Points to the first char of the string; Tam := (Length(SInput))+1; // Size the string POutput := StrAlloc(tam); // Allocate; CopyMemory(POutput,pt,tam); // Do the copy POutput[tam-1] := #0; // Put the null to finish MessageBox(0, POutput, 'Algo', MB_ICONWARNING or MB_OK); StrDispose(POutput); end; 

这是有效的,因为内部ShortString是Char的数组[0..255]。 我手头没有D2009来查看SizeOf(char)是否必须更改为SizeOf(AnsiChar)。 原理是一样的:分配PAnsiChar,将指针指向ShortString的第一个char,然后复制(在这种情况下,我已完成CopyMemory)到PAnsiChar。 并将null放在它的位置。

或者你可以去mghie的方式创建一个包装器并在那里进行演员表演 。