Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Problems with Explicit Access of C++ dll from Delphi

Posted on 2008-10-08
4
Medium Priority
?
935 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 21

Assisted Solution

by:developmentguru
developmentguru earned 600 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 600 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

In our object-oriented world the class is a minimal unit, a brick for constructing our applications. It is an abstraction and we know well how to use it. In well-designed software we are not usually interested in knowing how objects look in memory. …
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…

715 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