如何在C#中使用Delphi的Dll(用PChar类型型) [英] How to use Delphi Dll(with PChar type) in C#
问题描述
下面是德尔福DLL的代码:
Here is the Delphi DLL code:
library Project2;
uses
SysUtils,
Classes;
{$R *.res}
function SimpleConv(const s: string): string;
var
i: Integer;
begin
Result := '';
for i := 1 to Length(s) do
if Ord(S[i]) < 91 then
Result := Result + S[i];
end;
function MsgEncode(pIn: pchar; InLen: Integer; var pOut: pchar; var OutLen: Integer): Boolean; stdcall;
var
sIn: string;
sOut: string;
begin
SetLength(sIn, InLen);
Move(pIn^, sIn[1], InLen);
sOut := SimpleConv(sIn); // Do something
OutLen := Length(sOut);
GetMem(pOut, OutLen);
Move(sOut[1], pOut^, OutLen);
Result := OutLen > 0;
end;
procedure BlockFree(Buf: pchar); stdcall;
begin
if assigned(Buf) then
FreeMem(Buf);
end;
exports
MsgEncode,
BlockFree;
begin
end.
DLL函数MsgEncode将allocmem噘嘴参数,并且BlockFree用于释放其中alloced内存由MsgEncode
The Dll function MsgEncode will allocmem to pOut param, and the BlockFree is used to free the memory which alloced by MsgEncode.
我的问题是:如何使用这个DLL在C#中?我在C#中的新手。
推荐答案
我打算把你的面值的问题,与一些附带条件:
I'm going to take your question at face value, with a few provisos:
- 无论您使用的是Unicode的德尔福与否是至关重要的使用要知道互操作的代码
PChar类型
,因为PChar类型
属于ANSIChar
之间浮动和WideChar
根据德尔福的版本。我假定你使用Unicode德尔福。如果没有,那么你需要改变字符串为P编组/调用方。 - 我修改您的DLL的代码。我已删除了长度参数和我的工作,前提是,你只打算让受信任的代码调用此DLL。不可信代码可能会产生缓冲区溢出,但你不会让你的机器上运行不受信任的代码,是吗?
- 我也改变了
BlockFree
,以便它可以接收一个无类型指针。没有必要为它是类型为PChar类型
,它只是调用免费
。
- Whether you are using a Unicode Delphi or not is essential to know for interop code using
PChar
becausePChar
floats betweenAnsiChar
andWideChar
depending on the version of Delphi. I've assumed that you use Unicode Delphi. If not then you'd need to change the string marshalling at the P/Invoke side. - I've modified your DLL code. I've removed the length parameters and am working on the assumption that that you are only going to let trusted code call this DLL. Untrusted code could produce buffer overruns but you aren't going to let untrusted code run on your machine, are you?
- I've also changed
BlockFree
so that it can receive an untyped pointer. There's no need for it to be types asPChar
, it's just callingFree
.
下面是修改后的Delphi代码:
Here's the modified Delphi code:
library Project2;
uses
SysUtils;
{$R *.res}
function SimpleConv(const s: string): string;
begin
Result := LowerCase(s);
end;
function MsgEncode(pIn: PWideChar; out pOut: PWideChar): LongBool; stdcall;
var
sOut: string;
BuffSize: Integer;
begin
sOut := SimpleConv(pIn);
BuffSize := SizeOf(Char)*(Length(sOut)+1);//+1 for null-terminator
GetMem(pOut, BuffSize);
FillChar(pOut^, BuffSize, 0);
Result := Length(sOut)>0;
if Result then
Move(PChar(sOut)^, pOut^, BuffSize);
end;
procedure BlockFree(p: Pointer); stdcall;
begin
FreeMem(p);//safe to call when p=nil
end;
exports
MsgEncode,
BlockFree;
begin
end.
和这里的另一边的C#代码:
And here's the C# code on the other side:
使用System.Runtime.InteropServices
;
using System; using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("project2.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MsgEncode(string pIn, out IntPtr pOut);
[DllImport("project2.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern void BlockFree(IntPtr p);
static void Main(string[] args)
{
IntPtr pOut;
string msg;
if (MsgEncode("Hello from C#", out pOut))
msg = Marshal.PtrToStringAuto(pOut);
BlockFree(pOut);
}
}
}
这应该让你开始。既然你是新的C#中,您将需要做的的P / Invoke读了不少。尽情享受吧!
This should get you started. Since you are new to C# you are going to need to do quite a bit of reading up on P/Invoke. Enjoy!
这篇关于如何在C#中使用Delphi的Dll(用PChar类型型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!