Jump to content
Sign in to follow this  
TurboMagic

Calling a Delphi DLL from LabView

Recommended Posts

I'm writing a DLL which shall be called by LabView (among other environments).

Calling a simple function which gets 2 numbers, adds them and returns the result works.
That one uses calling convention cdecl, as specified by the "client".

 

But strings are a problem. For getting this tested I developed the following simple function,

which shall be called by a LabView test application but this always crashes inside the DLL.

Currently it crashes here: "Exception beim Stringrückliefern", if I make a var parameter out
of CalcRes it immediately crashes here: "Exception in Berechnung".

 

What might cause this? The caller shall pass a string which a number of chars allocated for

and the number of chars he allocated the string for + the #0 terminator in CalcResSize.

If the result fits in that, it is returned in the string. CalcResSize will represent the number of

bytes needed for the string including the #0 after the call so if the caller didn't pass a long
enough string he can call the function again using a longer string.

 

Here's the code:

 

uses
  System.SysUtils,
  System.AnsiStrings;

function Add(Number1, Number2: UInt8; CalcRes: PAnsiChar; var CalcResSize: UInt8): UInt16; cdecl;
var
  Res    : UInt16;
  ResStr : AnsiString;
begin
  try
    Res    := Number1 + Number2;
    ResStr := AnsiString(Res.ToString);
  except
    On E:Exception do
    begin
      OutputDebugString(PWideChar('Exception in Berechnung: ' + E.Message));
      Result := 2;
      Exit;
    end;
  end;

  try
    if Assigned(CalcRes) and ((Length(ResStr) {* SizeOf(Char)} + 1) <= CalcResSize) then
    begin
      System.AnsiStrings.StrPLCopy(CalcRes, ResStr, CalcResSize);
      Result := 0;
    end
    else
      Result := 1;
  except
    On E:Exception do
    begin
      OutputDebugString(PWideChar('Exception beim Stringrückliefern: ' + E.Message + ' / ' +
                        madExcept.GetCrashStackTrace));
      Result := 2;
      Exit;
    end;
  end;

  try
    CalcResSize := (Length(ResStr) {* SizeOf(Char)} + 1);
  except
    On E:Exception do
    begin
      OutputDebugString(PWideChar('Exception in CalcResSize Berechnung: ' + E.Message + ' / ' +
                        madExcept.GetCrashStackTrace));
      Result := 2;
      Exit;
    end;
  end;
end;

 

Cheers

 

TurboMagic

Share this post


Link to post
48 minutes ago, TurboMagic said:

System.AnsiStrings.StrPLCopy(CalcRes, ResStr, CalcResSize);

This is problem maker.

 

1) I would stay away from any string RTL string functions when it comes to passing raw data to/from different built DLL, use simple Move.

2) You already are checking Length against CalcResSize but you are using CalcResSize!!  you should copy only your string length as CalcResSize might be 10kb while your string is 3 bytes, can you see the problem now ?

3) In any case, E.Message and the Stack will be way more helpful to understand the bug, is it access violation ? and on what address ?

Share this post


Link to post

Thanks for the answer.
I changed it to use Move now like this:

Move(ResStr[1], CalcRes[0], Length(ResStr));

 

In my Delphi test application it works flawlessly, but the LabView application calling the DLL still crashes it.
Access violation at address 184E140E ... Read of address 00000003

 

I will try to log the address of the PChar passed in now and if possible it's contents at that time, but
I don't know how to read raw RAM for getting a bit more loginfo...

Share this post


Link to post
Posted (edited)

What happens, when this Add is called with nil as CalcRes?

Typically in C style API's function then assigns required string length without copying string. So that caller would know, how much memory to allocate.

 

Never mind. I did not read correctly original code, this is already handled.  But what are requirements on function result?

 

Also possible issues with ending #0 - is it required in CalcRes?

 

 

Edited by Virgo

Share this post


Link to post

BTW, you can debug DLLs by defining host process in Run options dialog. Then you can set breakpoints and see what's going on in fact.

 

Share this post


Link to post
Posted (edited)
15 hours ago, Kas Ob. said:

This is problem maker.

Nah, that's not going be to the cause of the error reported in the original post. 

 

Hard to say what is the problem though without knowing the other side of the interface. How can we know how the function is declared in labview? My expectation is that the real issue is a mismatch at the binary interface layer. 

Edited by David Heffernan

Share this post


Link to post
29 minutes ago, David Heffernan said:

Nah, that's not going be to the cause of the error reported in the original post. 

The line in full is what i meant, not StrPLCopy specifically, between the unchecked size (which is seem not the problem now) and the pointer type.

 

And you are right there, it is about the other side, is it simple pointer or something else ?

Share this post


Link to post

It works now, last failure was to not declare the last function parameter as pointer in the header file they use as this is a var param on my side.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×