从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); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |