非托管导出:使用 delphi 中的 C# 对象
Unmanaged exports: Consume C# object in delphi
我正在使用 "Unmanaged Exports" 库从 c# class 库中导出函数。对于具有简单签名的基本功能,这非常有效。现在我想导出我的 Delphi 应用程序想要使用的 C# 对象。以下代码编译:
[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class Sample
{
public string Text
{
[return: MarshalAs(UnmanagedType.BStr)]
get;
[param: MarshalAs(UnmanagedType.BStr)]
set;
}
[return: MarshalAs(UnmanagedType.BStr)]
public string TestMethod()
{
return Text + "...";
}
}
static class UnmanagedExports
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.IDispatch)]
static Object CreateSampleInstance()
{
try
{
return new Sample { Text = "xy" };
}
catch (Exception ex)
{
return null;
}
}
}
在我的 Delphi 应用程序中,我想通过以下代码加载 dll:
function CreateSampleInstance(): IDispatch; stdcall; external 'UnmanagedExports.dll';
procedure TForm3.Button2Click(Sender: TObject);
var
disp: IDispatch;
variant: OleVariant;
begin
CoInitialize(0);
disp := CreateSampleInstance();
variant := disp;
ShowMessage(variant.TestMethod());
end;
我的 Delphi-代码中出现空指针异常。我的签名一定有问题。有人知道如何让它工作吗?
更准确地遵循示例here(避免IDispatch/dual接口),它有效:
c#
using RGiesecke.DllExport;
using System;
using System.Runtime.InteropServices;
namespace MyLibrary
{
[ComVisible(true)]
[Guid("8871C5E0-B296-4AB8-AEE7-F2553BACB730"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISample
{
[return: MarshalAs(UnmanagedType.BStr)]
string GetText();
void SetText([MarshalAs(UnmanagedType.BStr)]string value);
[return: MarshalAs(UnmanagedType.BStr)]
string TestMethod();
}
public class Sample : ISample
{
public string Text { get; set; }
public string GetText()
{
return Text;
}
public void SetText(string value)
{
Text = value;
}
public string TestMethod()
{
return Text + "...";
}
}
public static class UnmanagedExports
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
public static void CreateSampleInstance([MarshalAs(UnmanagedType.Interface)] out ISample instance)
{
instance = null;
try
{
instance = new Sample { Text = "Hello, world" };
}
catch
{
}
}
}
}
delphi/lazarus
type
ISample = interface(IUnknown)
['{8871C5E0-B296-4AB8-AEE7-F2553BACB730}']
function GetText: WideString; safecall;
procedure SetText(const Value: WideString); safecall;
function TestMethod: WideString; safecall;
property Text: WideString read GetText write SetText;
end;
procedure CreateSampleInstance(out Sample: ISample); stdcall; external 'MyLibrary.dll';
...
var
Sample: ISample;
begin
CreateSampleInstance(Sample);
Writeln(Sample.Text);
Writeln(Sample.TestMethod);
Readln;
end;
我正在使用 "Unmanaged Exports" 库从 c# class 库中导出函数。对于具有简单签名的基本功能,这非常有效。现在我想导出我的 Delphi 应用程序想要使用的 C# 对象。以下代码编译:
[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class Sample
{
public string Text
{
[return: MarshalAs(UnmanagedType.BStr)]
get;
[param: MarshalAs(UnmanagedType.BStr)]
set;
}
[return: MarshalAs(UnmanagedType.BStr)]
public string TestMethod()
{
return Text + "...";
}
}
static class UnmanagedExports
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.IDispatch)]
static Object CreateSampleInstance()
{
try
{
return new Sample { Text = "xy" };
}
catch (Exception ex)
{
return null;
}
}
}
在我的 Delphi 应用程序中,我想通过以下代码加载 dll:
function CreateSampleInstance(): IDispatch; stdcall; external 'UnmanagedExports.dll';
procedure TForm3.Button2Click(Sender: TObject);
var
disp: IDispatch;
variant: OleVariant;
begin
CoInitialize(0);
disp := CreateSampleInstance();
variant := disp;
ShowMessage(variant.TestMethod());
end;
我的 Delphi-代码中出现空指针异常。我的签名一定有问题。有人知道如何让它工作吗?
更准确地遵循示例here(避免IDispatch/dual接口),它有效:
c#
using RGiesecke.DllExport;
using System;
using System.Runtime.InteropServices;
namespace MyLibrary
{
[ComVisible(true)]
[Guid("8871C5E0-B296-4AB8-AEE7-F2553BACB730"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISample
{
[return: MarshalAs(UnmanagedType.BStr)]
string GetText();
void SetText([MarshalAs(UnmanagedType.BStr)]string value);
[return: MarshalAs(UnmanagedType.BStr)]
string TestMethod();
}
public class Sample : ISample
{
public string Text { get; set; }
public string GetText()
{
return Text;
}
public void SetText(string value)
{
Text = value;
}
public string TestMethod()
{
return Text + "...";
}
}
public static class UnmanagedExports
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
public static void CreateSampleInstance([MarshalAs(UnmanagedType.Interface)] out ISample instance)
{
instance = null;
try
{
instance = new Sample { Text = "Hello, world" };
}
catch
{
}
}
}
}
delphi/lazarus
type
ISample = interface(IUnknown)
['{8871C5E0-B296-4AB8-AEE7-F2553BACB730}']
function GetText: WideString; safecall;
procedure SetText(const Value: WideString); safecall;
function TestMethod: WideString; safecall;
property Text: WideString read GetText write SetText;
end;
procedure CreateSampleInstance(out Sample: ISample); stdcall; external 'MyLibrary.dll';
...
var
Sample: ISample;
begin
CreateSampleInstance(Sample);
Writeln(Sample.Text);
Writeln(Sample.TestMethod);
Readln;
end;