非托管导出:在delphi

时间:2018-02-27 12:12:04

标签: c# delphi dllimport

我正在使用" Unmanaged Exports"库从c#类库中导出函数。对于具有简单签名的基本功能,这非常有用。现在我想导出一个我的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-Code中得到一个空指针异常。我的签名肯定有问题。任何人都知道如何使这个工作?

1 个答案:

答案 0 :(得分:3)

更精确地遵循示例here(避免使用IDispatch /双接口),它可以工作:

C#

public void Configure(IApplicationBuilder app)
{
    // basic stuff
    var config = services.GetService<IConfiguration>();
    string route = config.GetValue<string>("Path");

    app.UseMvc(routes => {
        routes.MapRoute("someName", route, new { controller = "myController", action = "myAction"});
    });
}

的Delphi /拉扎勒斯

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
            {
            }
        }
    }
}