加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

从C#调用Delphi函数

发布时间:2020-12-15 23:24:11 所属栏目:百科 来源:网络整理
导读:我有一个下面的DLL源代码. library Project1;uses System.SysUtils,System.Classes;type IStringFunctions = interface ['{240B567B-E619-48E4-8CDA-F6A722F44A71}'] function GetMethodValueAsString():PAnsiChar; stdcall; end; TStringFunctions = class(
我有一个下面的DLL源代码.

library Project1;

uses
  System.SysUtils,System.Classes;

type

  IStringFunctions = interface
    ['{240B567B-E619-48E4-8CDA-F6A722F44A71}']
    function GetMethodValueAsString():PAnsiChar; stdcall;
  end;

  TStringFunctions = class(TInterfacedObject,IStringFunctions)
  public
    function GetMethodValueAsString():PAnsiChar; stdcall;
  end;

{$R *.res}

function  TStringFunctions.GetMethodValueAsString():PAnsiChar; stdcall;
begin
  Result := 'test';
end;


procedure GetImplementation(out instance:IStringFunctions); stdcall; export;
begin
  instance := TStringFunctions.Create;
end;

exports GetImplementation;

begin
end.

我想在C#中使用这样的

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    [ComVisible(true)]
    [ComImport,InterfaceType(ComInterfaceType.InterfaceIsIUnknown),Guid("240B567B-E619-48E4-8CDA-F6A722F44A71")]
    public interface IStringFunctions
    {
        [MethodImplAttribute(MethodImplOptions.PreserveSig)]
        [return: MarshalAs(UnmanagedType.AnsiBStr)]
        string GetMethodValueAsString();
    }

    class Program
    {
        [DllImport("kernel32.dll",EntryPoint = "LoadLibrary",CallingConvention = CallingConvention.StdCall)]
        static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

        [DllImport("kernel32.dll",EntryPoint = "GetProcAddress",CallingConvention = CallingConvention.StdCall,CharSet = CharSet.Ansi)]
        static extern IntPtr GetProcAddress(int hModule,[MarshalAs(UnmanagedType.LPStr)] string lpProcName);

        [DllImport("kernel32.dll",EntryPoint = "FreeLibrary",CallingConvention = CallingConvention.StdCall)]
        static extern bool FreeLibrary(int hModule);

        [UnmanagedFunctionPointer(CallingConvention.StdCall,CharSet = CharSet.Ansi)]
        delegate void GetImplementation([MarshalAs(UnmanagedType.Interface)] out IStringFunctions instance);

        static void Main(string[] args)
        {
            const string dllName = "Project1.dll";
            const string functionName = "GetImplementation";

            int libHandle = LoadLibrary(dllName);
            if (libHandle == 0) throw new Exception(string.Format("Could not load library "{0}"",dllName));

            var delphiFunctionAddress = GetProcAddress(libHandle,functionName);
            if (delphiFunctionAddress == IntPtr.Zero) throw new Exception(string.Format("Can't find function "{0}" in library "{1}"",functionName,dllName));

            GetImplementation getImplementation = (GetImplementation)Marshal.GetDelegateForFunctionPointer(delphiFunctionAddress,typeof(GetImplementation));

            if (getImplementation != null)
            {
                IStringFunctions instance = null;
                getImplementation(out instance);

                if (instance != null)
                {
                    //!!! don't return value !!!!
                    String result = instance.GetMethodValueAsString();
                    Console.WriteLine(result);
                }
            }
            Console.ReadLine();
        }
    }
}

但是instance.GetMethodValueAsString方法不起作用.并退出代码.

我想在c#中使用来自dll函数(GetMethodValueAsString)的返回值.

我不明白.

哪里是我的错?

非常感谢

解决方法

[return: MarshalAs(UnmanagedType.AnsiBStr)]

这是错的.您没有返回在COM堆上分配的ANSI编码字符串.您将返回一个普通的C字符串,一个指向以null结尾的ANSI字符数组的指针.

您的接口声明应该是:

[MethodImplAttribute(MethodImplOptions.PreserveSig)]
IntPtr GetMethodValueAsString();

调用方法必须像这样:

IntPtr ptr = instance.GetMethodValueAsString();
string result = Marshal.PtrToStringAnsi(ptr);

当然,当您需要返回动态分配的字符串时,您的界面设计变得相当不切实际.您还需要导出解除分配器.解决这个问题的干净方法是使用BSTR.像这样:

德尔福

IStringFunctions = interface
  ['{240B567B-E619-48E4-8CDA-F6A722F44A71}']
  procedure GetMethodValueAsString(out value: WideString); stdcall;
end;

C#

[MethodImplAttribute(MethodImplOptions.PreserveSig)]
void GetMethodValueAsString([MarshalAs(UnmanagedType.BStr)] out string result);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读