Home > OS >  C# P/Invoked function from BPL returns same pointer to Delphi record regardless of input
C# P/Invoked function from BPL returns same pointer to Delphi record regardless of input

Time:01-08

I am trying to use a function from foreign BPL package for which I don't have access to code.

While I have success in Delphi, in C# I am still getting same value, regardless of input.

External usage of BPL in Delphi

type
  PRecord = ^TRecord;
  TRecord = packed record
      S: string;
      LW: LongWord;
  end;    

function GetValue(W : Word) : PRecord; external 'package.bpl' name '@Unit@Function$qqrus';

Calling of GetValue() with different input returns different records, which is correct.

External usage of BPL in C#

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TRecord
{
    public string S;
    public int LW;
}
        
[DllImport("package.bpl", EntryPoint = "@Unit@Function$qqrus", CharSet = CharSet.Unicode)]
static extern IntPtr GetValue(ushort number);
    
public static TRecord GetDelphiValue(ushort number)
{
    var ptr = GetValue(number);
    return (TRecord) Marshal.PtrToStructure(ptr, typeof(TRecord))
}

Calling of GetDelphiValue() with different input always returns the same pointer and therefore the struct.

What I've missed?

CodePudding user response:

function GetValue(W : Word) : PRecord; 
  external 'package.bpl' name '@Unit@Function$qqrus';

This function uses Delphi's default calling convention, namely register. This is not supported by other tools, and so this function cannot be called from your C# code.

You will need to put a Delphi DLL in between your C# code and the Delphi package. That Delphi DLL will be able to call the register calling convention function, and can export a function with the stdcall calling convention for your C# code to call.

Additionally, you also have the opportunity to sort out any potential issues caused by the use of the Delphi string type, which again is private to Delphi.

For what it worth, I am highly sceptical that the function really does return a pointer to a record. I think it is more likely that this is a procedure that has the record as a var or out parameter. And I do think that there are very likely issues relating to the lifetime of that string. Realistically, you cannot expect to use a binary module for which you have no information about its interface.

  •  Tags:  
  • Related