Call Delphi XE6 unicode dll from C# asp.net

242 Views Asked by At

before opening the topic searched any more responses served me, my error remains, have created a dll in Delphi XE6 64x which is as follows:

function GeraChave(Action : PAnsiChar; StrCrip : PAnsiChar; Cnpj : PAnsiChar; idPC: PAnsiChar): PAnsiChar; stdcall;
var
 KeyLen : Integer;
 KeyPos : Integer;
 OffSet : Integer;
 Dest, Key : String;
 SrcPos : Integer;
 SrcAsc : Integer;
 TmpSrcAsc : Integer;
 Range, I : Integer;
 matKey : Array[0..7] of String;
begin
  if (StrCrip = '') Then
  begin
    Result:= '';
    Exit;
  end;

  for I := 0 to 8 do
    matKey[I] := Copy(idPC, I, 1);

  Key := 'A#%tgNh*'+ matKey[0] +'UJklo'+ matKey[1] + 'O' + cnpj + 'O' +
         '798DS'+ matKey[2] +'Cea'+ matKey[3] +'SEc%7*I'+ matKey[4] +'u@Ed#'+
         matKey[5] +'f$f'+ matKey[6] +'%g&j-9'+ matKey[7] +'sc';

  Dest := '';
  KeyLen := Length(Key);
  KeyPos := 0;
  SrcPos := 0;
  SrcAsc := 0;
  Range := 256;

  if (Action = UpperCase('C')) then
  begin
    Randomize;
    OffSet := Random(Range);
    Dest := Format('%1.2x',[OffSet]);
    for SrcPos := 1 to Length(StrCrip) do
    begin
      SrcAsc := (Ord(StrCrip[SrcPos]) + OffSet) Mod 255;
      if KeyPos < KeyLen then KeyPos := KeyPos + 1 else KeyPos := 1;

      SrcAsc := SrcAsc Xor Ord(Key[KeyPos]);
      Dest := Dest + Format('%1.2x',[SrcAsc]);
      OffSet := SrcAsc;
    end;
  end
  Else if (Action = UpperCase('D')) then
  begin
    OffSet := StrToInt('$' + copy(StrCrip,1,2));
    SrcPos := 3;
    repeat
      SrcAsc := StrToInt('$' + copy(StrCrip,SrcPos,2));
      if (KeyPos < KeyLen) Then KeyPos := KeyPos + 1 else KeyPos := 1;
      TmpSrcAsc := SrcAsc Xor Ord(Key[KeyPos]);
      if TmpSrcAsc <= OffSet then TmpSrcAsc := 255 + TmpSrcAsc - OffSet
      else TmpSrcAsc := TmpSrcAsc - OffSet;
      Dest := Dest + Chr(TmpSrcAsc);
      OffSet := SrcAsc;
      SrcPos := SrcPos + 2;
    until (SrcPos >= Length(StrCrip));
  end;

 Result := PAnsiChar(Dest);
end;

 Exports
 GeraChave;

 begin
end.

My C # .NET code looks like this:

public partial class _Default : System.Web.UI.Page
{

    [DllImport(@"H:\FTP\HOME\Web\testes\dllDelphi\Bin\DllChave.dll", 
               CallingConvention = CallingConvention.StdCall,
               CharSet = CharSet.Ansi)]

    public static extern string GeraChave(string xAction, string StrCrip, string Cnpj, string idPC);

    protected void Page_Load(object sender, EventArgs e)
    {
        string str = "A75BD3FD" + "|15/12/2016|" + "04564521020004";
        string xTp = "C";
        string Cnpj = "04564521020004";
        string IDPC = "A75BD3FD";
        string xRes = "";

        xRes = GeraChave(xTp, str, Cnpj, IDPC);

    }
}

and when I call the DLL is the error "BadImageFormatException was unhandled by user code"

thanks!

2

There are 2 best solutions below

7
On BEST ANSWER

BadImageFormatException typically indicates a bitness mismatch. Your Delphi module is 64 bit and the C# module is 32 bit, or vice versa.

You have other problems. At least the following:

  • You cast a UTF-16 UnicodeString string to PAnsiChar. That cast is not correct.
  • You return a the address of a local variable. The local variable goes out of scope when the function returns. Thus you are returning a pointer to invalid memory. You need to find another way to return that buffer.
  • Your C# code assumes that the returned value was allocated by a call to CoTaskMemAlloc. It will thus call CoTaskMemFree on the pointer you returned, which is clearly wrong. That issue will dissolve though when you solve the above issue.

I'd probably return the string as a WideString out parameter and match that with UnmanagedType.BStr on the C# side: Why can a WideString not be used as a function return value for interop? That allows the callee to allocate the string and the caller to deallocate.

0
On

I decided this way:

On Delphi

function GeraChave(xAction : PChar; StrCrip : PChar; Cnpj : PChar; idPC: PChar; Saida : PChar; len : Integer): Integer; stdcall;
begin
 StrLCopy(Saida, PChar(Dest), len);
 Result := 1;
end;

On C#

public static extern int GeraChave(string xAction, string StrCrip, string Cnpj, string idPC, StringBuilder Saida, int len);
    StringBuilder str = new StringBuilder(256);
    int retval = GeraChave(xTp, strCrip, Cnpj, IDPC, str, str.Capacity);