3

I know few basics of Delphi (In fact I've been using it for few years)...

I'm hitting a wall with DLL's (never really play with this).

Consider this example:

   unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

Type FT_Result = Integer;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;
  FT_HANDLE : DWord = 0;



implementation

{$R *.dfm}

function I2C_GetNumChannels(numChannels: dword):FT_Result; stdcall; external 'libmpsse.dll' name 'I2C_GetNumChannels';
function I2C_OpenChannel(index:dword;handle:pointer):FT_Result; stdcall; external 'libmpsse.dll' name 'I2C_OpenChannel';

procedure TForm1.Button1Click(Sender: TObject);
var
numofchannels:dword;
begin
i2c_getnumchannels(numofchannels);
showmessage(inttostr(numofchannels));
end;

end.

I need to interface the libmpsse.dll from FTDI to access a I2C device on the USB port.
When i'm calling the function I2C_GetNumChannels I get tons of AccessViolation...

I just want to know what's wrong with the dll function?

Also I2C_GetNumChannels is supposed to returns 2 values...

enter image description here

From the official API guide here -->http://www.ftdichip.com/Support/Documents/AppNotes/AN_177_User_Guide_For_LibMPSSE-I2C.pdf

Thank you very much!

Regards

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
ELCouz
  • 572
  • 2
  • 6
  • 17

1 Answers1

6

Your translation is incorrect. It should be:

function I2C_GetNumChannels(out numChannels: Longword): FT_Result;
  stdcall; external 'libmpsse.dll';

The function you are calling accepts the address of a 32 bit unsigned integer. Your translation passed a 32 bit unsigned integer by value.

You could translate the import using pointers but it's easier for the caller to do it using a var or out parameter, as I have done.

I'm assuming that you have correctly determined that the calling convention is stdcall. You'd need to check the header file to know for sure.

You should check the value returned from the function call for errors. This is the single most common mistake that people make when calling external libraries. Don't ignore return values. Check for errors.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    You are right! Thanks sir switched to CDECL (stdcall was creating access violation) – ELCouz Jan 01 '15 at 20:24
  • 1
    function I2C_GetNumChannels(out numChannels: Longword): FT_Result;cdecl; external 'libmpsse.dll'; is the correct answer – ELCouz Jan 01 '15 at 20:25
  • That may be correct but don't use trial and error. Check in the header file. – David Heffernan Jan 01 '15 at 20:25
  • I have only a C header file... where do I look for? – ELCouz Jan 01 '15 at 20:26
  • In that header file. That will have the answer. If a calling convention is not specified then the default will be cdecl. – David Heffernan Jan 01 '15 at 20:27
  • No calling convention described in the file header assuming CDECL – ELCouz Jan 01 '15 at 20:35
  • Thank you very much! We found it at the same time mine was : function I2C_GetNumChannels(var numChannels: cardinal):FT_Result; cdecl; external 'libmpsse.dll' name 'I2C_GetNumChannels'; – ELCouz Jan 01 '15 at 20:35
  • Don't specify the name like that. It is unnecessary. – David Heffernan Jan 01 '15 at 20:41
  • Yes I know, it's redundant! I've used your version since answer has been accepted! Well I've learn so much with DLL's today :) – ELCouz Jan 01 '15 at 21:06
  • 1
    About calling conventions, and how to determine them, please read my article [Pitfalls of converting](http://www.rvelthuis.de/articles/articles-convert.html#cconvs). It explains a lot about header translations. – Rudy Velthuis Jan 03 '15 at 11:33