-1

I have a DLL written in Delphi from where i know only his signature like:

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

I am having some trouble calling this DLL method from C#. The method supposed to also transport some data in the ParamStream and return true if everything went fine.

I have tried the following(and other various changes in the DLL's method parameters) but unsuccessful(each time i was calling this function using references or out parameters i was getting errors):

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

My guess is that i did not understood how to translate the signature in a proper way to use it in C#. I can provide more info if needed(like the errors i got, but mostly they are corrupt memory).

Warren P
  • 65,725
  • 40
  • 181
  • 316
avi
  • 912
  • 8
  • 22
  • I think you want to use `System.Runtime.InteropServices.ComTypes.IStream` – dmeglio Oct 01 '15 at 16:06
  • I would expect you're confused a little bit. .NET Object types like C# Streams can not be meaningfully passed to Delphi, unless we introduce some .NET interop code that would be very difficult to write, on the Delphi side. What you are doing is in fact, insane. – Warren P Oct 02 '15 at 12:47
  • Indeed, using the Stream object was a mistake. Like David Heffernan said, using an IStream interface, with an basic wrapper did the trick. – avi Oct 02 '15 at 14:44

1 Answers1

1

Your translation is wrong. I'm not sure how you converted an out param of type DWORD into char[]. That should be out uint. And the Stream should not be ref, and furthermore needs to be the IStream interface rather than the Stream class.

The p/invoke should be like so:

[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
);

Note that this assumes a Delphi version of 2007 or earlier, where PChar maps to PAnsiChar. If the Delphi version is later than that, and PChar is PWideChar, then use CharSet.Unicode.

I've also assumed that all of the string parameters are for passing data from the caller to the callee. But probably the final string parameter, Error does not not have those semantics. It's probably for passing error text out. So that then should be implemented with StringBuilder in place of string.

Of course, you are going to need to obtain an implementation of IStream from somewhere. For instance: Creating IStream object in C#. It's hard for me to advise you on this because you've not provided any of the important details of how to call the function. And you've changed the names of all the parameters so that we cannot guess the semantics.

I can see this question becoming something of a train wreck as your debugging proceeds. I hope I am proved wrong.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I have finally managed to get that stream information. Indeed your p/invoke observation helped. Thank you for your help! – avi Oct 02 '15 at 14:32
  • I have not provided more details because unfortunatly i only have a limited documentation about the dll i used, and the fields are names in an exotic language. – avi Oct 02 '15 at 14:41