调用Delphi DLL并向其传递c#流

本文关键字:Delphi DLL 调用 | 更新日期: 2023-09-27 18:15:27

我有一个用Delphi编写的DLL,从那里我只知道他的签名,如:

function GeResultToStream(Param1: PChar; Param2: PChar; Param3:PChar; Param4: integer; out Param5: DWord; ParamStream: IStream; Error: PChar; ErrorSize: integer):BOOL;stdcall; external 'MYDLL.dll';

我有一些麻烦从c#调用这个DLL方法。如果一切正常,该方法还应该在ParamStream中传输一些数据,并返回true

我尝试了以下方法(以及DLL方法参数中的其他各种更改),但不成功(每次我使用引用或输出参数调用此函数时,我都得到错误):

public class TestDLL
    {
        internal class DLLInternal
        {
            const string _dllLocation = "MYDLL.dll";
           [DllImport(_dllLocation,
                        CallingConvention = CallingConvention.StdCall,
                        CharSet = CharSet.Ansi,
                        EntryPoint = "GeResultToStream")]
            public static extern bool GeResultToStream(string Param1, string Param2, string Param3, int Param4, char[] Param5, ref  Stream ParamStream, string Error, int ErrorSize);
        }
        public TestDLL()
        {
        }
        ~TestDLL()
        {
        }
        public Stream GetStream(string Param1, string Param2, string Param3, int Param4, char[] Param5, string Error, int ErrorSize)
        {
            try
            {
                Stream stream = new MemoryStream();              
                bool x = DLLInternal.GeResultToStream(Param1, Param2, Param3, Param4, Param5, ref stream, Error, ErrorSize);     
                //here i think i might need to use somehow the Marshal class
                return stream;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception GetStream:" + ex.ToString());
                return null;
            }
        }
    }

我的猜测是,我不明白如何翻译签名以正确的方式在c#中使用它。如果需要,我可以提供更多的信息(如我得到的错误,但大多数情况下它们是损坏的内存)。

调用Delphi DLL并向其传递c#流

你的翻译错了。我不确定你是如何将DWORD类型的out参数转换为char[]的。应该是out uintStream不应该是ref,而且需要是IStream接口而不是Stream类。

p/调用应该是这样的:

[DllImport(_dllLocation, CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi, EntryPoint = "GeResultToStream")]
public static extern bool GeResultToStream(
    string Param1, 
    string Param2,
    string Param3, 
    int Param4, 
    out uint Param5, 
    ComTypes.IStream ParamStream, 
    string Error,
    int ErrorSize
);

注意,这假设Delphi的2007或更早版本,其中PChar映射到PAnsiChar。如果Delphi版本高于此版本,且PCharPWideChar,则使用CharSet.Unicode

我还假设所有的字符串参数都用于将数据从调用者传递给被调用者。但可能最后一个字符串参数,Error没有这些语义。可能是用来传递错误文本的。因此,应该用StringBuilder代替string来实现。

当然,您需要从某处获得IStream的实现。例如:在c#中创建IStream对象。我很难在这方面给你建议,因为你没有提供任何关于如何调用这个函数的重要细节。而且你已经更改了所有参数的名称,所以我们无法猜测语义。

我可以看到,随着调试的进行,这个问题变得有点像火车残骸。我希望我是错的。