Solved

Problems with Explicit Access of C++ dll from Delphi

Posted on 2008-10-08
4
905 Views
Last Modified: 2013-12-14
I have a C++ dll that I have created an import unit for and can sucessfully call two of the procedures
     CG4_Main_GetConnectedScanner
     CG4_GetApiVersion

The other two listed procedures return error code -616 which is means scanner type is not supported even though the scanner type is taken from the call to CG4_Main_GetConnectedScanner.  The code acts as it should in C++ - what am I missing??

I have pasted the import unit, the Delphi code, and a piece of C++ code that works below
*****************************************************************
Here is the import unit code I created (edited several other functions not relevant)
unit CG4ESSENTIALSAPI;

interface
uses
{$IFDEF WIN32}
  Windows;
{$ELSE}
  Wintypes, WinProcs;
{$ENDIF}

//{$INCLUDE "windows.h"}



const
  CG4_MAX_STR_LEN = 128; {///< Required buffer length for string parameters}


{///////////////////////////////////////////////////////////////////////////////// }
{/// struct & enum }


{//// Container to hold version information. }
type
  CG4ApiVersion = record
    Product: Array[0..CG4_MAX_STR_LEN-1] of Char;
    SdkVer: Array[0..CG4_MAX_STR_LEN-1] of Char;
    MosaicVer: Array[0..CG4_MAX_STR_LEN-1] of Char;
  end {tagCG4ApiVersion};

{/// Connected scanner }
type
  CG4ScannerExist = record
    nDevConnected: Integer;
    bCS500i: Bool;
    bCS500e: Bool;
    bCSD450: Bool;
    bCSD330: Bool;
    bCSD200: Bool;
  end {tagCG4ScannerExist};


{/// Scanner type }
type
  tagCG4ScannerType = (
    CG4_SCANNER_ONE_FINGER {= 300},
    CG4_SCANNER_CSD301 {= CG4_SCANNER_ONE_FINGER+1},
    CG4_SCANNER_CSD330 {= CG4_SCANNER_ONE_FINGER+2},
    CG4_SCANNER_CSD200 {= CG4_SCANNER_ONE_FINGER+3},
    CG4_SCANNER_TWO_FINGER {= 400},
    CG4_SCANNER_CSD450 {= CG4_SCANNER_TWO_FINGER+1},
    CG4_SCANNER_FOUR_FINGER {= 500},
    CG4_SCANNER_CS500I {= CG4_SCANNER_FOUR_FINGER+1},
    CG4_SCANNER_CS500E {= CG4_SCANNER_FOUR_FINGER+2},
    CG4_SCANNER_PALM {= 600},
    {/// ...  );



{///////////////////////////////////////////////////////////////////////////////// }
{/// Interface }

{///------------------------------------------------------------------- }
{/// Function name: CG4_Main_GetConnectedScanner }
{/// Parameter: }
{/// input: }
{/// output: }
{/// in/out: info - connected scanner; memory provided by caller! }
{/// Return: }
{/// CG4_STATUS_OK }
{/// CG4_ERR_INVALID_PARAM_VALUE }
{/// Description: Get connected scanner. }
{///------------------------------------------------------------------- }

function CG4_Main_GetConnectedScanner(var scannerExist: CG4SCANNEREXIST): Integer {$IFDEF WIN32} stdcall {$ENDIF};

{///------------------------------------------------------------------- }
{/// Function name: CG4_Main_GetAPIVersion }
{/// Parameter: }
{/// input: }
{/// output: }
{/// in/out: info - API version information; memory provided by caller! }
{/// Return: }
{/// CG4_STATUS_OK }
{/// CG4_ERR_INVALID_PARAM_VALUE }
{/// Description: Get DLL version information. }
{///------------------------------------------------------------------- }

function CG4_Main_GetAPIVersion(var info: CG4APIVERSION): Integer {$IFDEF WIN32} stdcall {$ENDIF};

{///------------------------------------------------------------------- }
{/// Function name: CG4_Main_Initialize }
{/// Parameter: }
{/// input: ScannerType - scanner type; default value is CG_SCANNER_CS500I }
{/// output: }
{/// in/out: }
{/// Return: }
{/// CG4_STATUS_OK }
{/// CG4_ERR_IS_INITIALIZED }
{/// CG4_ERR_DEVICE_IO }
{/// Description: Initialize scanner. }
{///------------------------------------------------------------------- }

function CG4_Main_Initialize(ScannerType: CG4SCANNERTYPE=CG4_SCANNER_CS500I): Integer {$IFDEF WIN32} stdcall {$ENDIF};

{///------------------------------------------------------------------- }
{/// Function name: CG4_Main_DeInitialize }
{/// Parameter: }
{/// input: }
{/// output: }
{/// in/out: }
{/// Return: }
{/// CG4_STATUS_OK }
{/// Description: DeInitialize scanner. }
{///------------------------------------------------------------------- }

function CG4_Main_FastStartup(ScannerType: CG4SCANNERTYPE=CG4_SCANNER_CS500I): Integer {$IFDEF WIN32} stdcall {$ENDIF};

{///------------------------------------------------------------------- }
{/// Function name: CG4_Main_StandBy }
{/// Parameter: }
{/// input: }
{/// output: }
{/// in/out: }
{/// Return: }
{/// CG4_STATUS_OK }
{/// Description: StandBy scanner. }
{///------------------------------------------------------------------- }

{///////////////////////////////////////////////////////////////////////////////// }

implementation

function CG4_Main_GetConnectedScanner; external 'CG4ESSENTIALSAPI.DLL';
function CG4_Main_GetAPIVersion; external 'CG4ESSENTIALSAPI.DLL';
function CG4_Main_Initialize; external 'CG4ESSENTIALSAPI.DLL';
function CG4_Main_FastStartup; external 'CG4ESSENTIALSAPI.DLL';

end.

************************************************************************
Here is a test Delphi code

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Button2: TButton;
    Edit2: TEdit;
    Button3: TButton;
    Edit3: TEdit;
    Button4: TButton;
    Edit4: TEdit;
    Button5: TButton;
    Edit5: TEdit;
    Button6: TButton;
    Edit6: TEdit;
    Button7: TButton;
    Edit7: TEdit;
    Button8: TButton;
    Edit8: TEdit;
    Button0: TButton;
    Edit0: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure Button0Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  se:tCG4ScannerExist;
  st:tCG4ScannerType;
  sa:tCG4ApiVersion;

implementation

{$R *.dfm}



procedure TForm1.Button0Click(Sender: TObject);
  var
    i:integer;
    t:string;
  begin
    i:=CG4_Main_GetConnectedScanner(se);
    t:=IntToStr(se.nDevConnected)+' Scanner(s) connected - ';
    if se.bCS500i then
      begin
        st:=CG4_SCANNER_CS500I;
        t:=t+'500i, ';
      end;
    if se.bCS500e then
      begin
        st:=CG4_SCANNER_CS500E;
        t:=t+'500e, ';
      end;
    if se.bCSD450 then
      begin
        st:=CG4_SCANNER_CSD450;
        t:=t+'450, ';
      end;
    if se.bCSD330 then
      begin
        st:=CG4_SCANNER_CSD330;
        t:=t+'300, ';
      end;
    if se.bCSD200 then
      begin
        st:=CG4_SCANNER_CSD200;
        t:=t+'200, ';
      end;
    Edit0.Text:=t;
  end;

procedure TForm1.Button1Click(Sender: TObject);
  var
    i:integer;
  begin
    i:=CG4_Main_GetApiVersion(sa);
    Edit1.Text:=IntToStr(i)+', '+sa.Product+', '+sa.SdkVer+', '+sa.MosaicVer;
  end;

procedure TForm1.Button2Click(Sender: TObject);
  var
    i:integer;
  begin
    i:=CG4_Main_Initialize(st);
    Edit2.Text:=IntToStr(i)
  end;

procedure TForm1.Button8Click(Sender: TObject);
  var
    i:integer;
  begin
    i:=CG4_Main_DeInitialize;
    Edit8.Text:='Attempted DeInitialize '+IntToStr(i)
  end;

end.

*************************************************************************
here is the working C++ code
void CDlgMainFunctions::OnBtnInitialize()
{
    int nRc = 0;
    FunctionStatus fs( m_pMainFrame, "Initialize()", nRc );

    m_pMainFrame->SetBusy();
    UpdateData();

    // get connected scanner
    CG4ScannerExist tScannerExist;
    nRc = CG4_Main_GetConnectedScanner(&tScannerExist);
    if (nRc != CG4_STATUS_OK || tScannerExist.nDevConnected != 1)
    {
        m_pMainFrame->ShowResult( "CG4_Main_GetConnectedScanner failed, returned code: %d", nRc );
        return;
    }

    RECT rect;

    if (tScannerExist.bCS500i)
    {
        m_ScannerType = CG4_SCANNER_CS500I;
        rect.left = 10; rect.right = 410; rect.top = 10; rect.bottom = 385;
    }
    else if (tScannerExist.bCS500e)
    {
        m_ScannerType = CG4_SCANNER_CS500E;
        rect.left = 10; rect.right = 410; rect.top = 10; rect.bottom = 385;
    }
    else if (tScannerExist.bCSD450)
    {
        m_ScannerType = CG4_SCANNER_CSD450;
        rect.left = 10; rect.right = 410; rect.top = 10; rect.bottom = 385;
    }
    else if (tScannerExist.bCSD330)
    {
        m_ScannerType = CG4_SCANNER_CSD330;
        rect.left = 10; rect.right = 260; rect.top = 10; rect.bottom = 260;
    }
    else if (tScannerExist.bCSD200)
    {
        m_ScannerType = CG4_SCANNER_CSD200;
        rect.left = 10; rect.right = 170; rect.top = 10; rect.bottom = 250;
    }
    m_pMainFrame->SetPreviewRect(rect);

    // init device
    nRc = CG4_Main_Initialize(m_ScannerType);
    if (nRc != CG4_STATUS_OK)
    {
        m_pMainFrame->ShowResult( "CG4_Main_Initialize failed, returned code: %d", nRc );
        return;
    }

}



0
Comment
Question by:tjmadden
  • 2
  • 2
4 Comments
 
LVL 21

Assisted Solution

by:developmentguru
developmentguru earned 150 total points
ID: 22678919
One of the first things I look at when having issues importing functions from DLLs is whether or not the functions are declared as STDCALL.  Try that and let me know how it goes.
0
 

Author Comment

by:tjmadden
ID: 22679358
All functions are declared as STDCALL (as in sample code).  I also tries CDECL with no luck.  The two functions that I have not been able to get working have defaults for the arguments - I am not sure if this needs to be handled differently?
0
 
LVL 21

Assisted Solution

by:developmentguru
developmentguru earned 150 total points
ID: 22689636
I think your intuition is probably correct on the defaults.  Try taking off the default value and make a different function that takes no parameters as the one that uses the default (overload if possible).
0
 

Accepted Solution

by:
tjmadden earned 0 total points
ID: 22690194
I figured it out - simple mistake in the type definitions that took me forever to figure out :(  feeling a little stupid - thanks for the help
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand columnThat will then direct you to their download page.From that page s…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question