Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Importing a Routine Under a Different Name from a Dynamic Link Library


This question is answered. Helpful answers available: 0. Correct answers available: 1.


Permlink Replies: 21 - Last Post: Feb 13, 2018 1:51 AM Last Post By: john smith
roca robin

Posts: 140
Registered: 9/10/06
Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 19, 2018 2:54 PM
this is a Delphi code line,(Delphi Rocks!)
function MessageBox(HWnd: Integer; Text, Caption: PChar; Flags: Integer): Integer; stdcall; external 'user32.dll' name 'MessageBoxA';

the line is from here,
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Procedures_and_Functions_(Delphi)

can someone convert this line into c++builder,
function xFunction_or_Procedure(num1: Integer=0; num2: Integer = 0): Pointer; stdcall; external 'TheDll_Iwant.DLL' name '_WantToProgram@14';

How do we write that code in (C++Builder Steel)?

roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 21, 2018 12:34 AM   in response to: roca robin in response to: roca robin
roca robin wrote:
this is a Delphi code line,(Delphi Rocks!)
function MessageBox(HWnd: Integer; Text, Caption: PChar; Flags: Integer): Integer; stdcall; external 'user32.dll' name 'MessageBoxA';

the line is from here,
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Procedures_and_Functions_(Delphi)

can someone convert this line into c++builder,
function xFunction_or_Procedure(num1: Integer=0; num2: Integer = 0): Pointer; stdcall; external 'TheDll_Iwant.DLL' name '_WantToProgram@14';

How do we write that code in (C++Builder Steel)?


I tried this one,, but doesn't work, error message is "write of address at" or sometimes "priviledge instruction at"

HMODULE hModule = LoadLibrary(TEXT("my.dll")); //my.dll is a visual studio 2013 compile dll
typedef void* (*MYFUNC)(int num1 = 1, int num2 = 2);
MYFUNC UseMyFunctionX = (MYFUNC) GetProcAddress(hModule, "_myFunctionName@10");

any suggestions ?
Alex Belo

Posts: 626
Registered: 10/8/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 21, 2018 6:51 AM   in response to: roca robin in response to: roca robin
roca robin wrote:

I tried this one, but doesn't work
...
HMODULE hModule = LoadLibrary(TEXT("my.dll"));
//my.dll is a visual studio 2013 compile dll

Check result according to

LoadLibrary
https://msdn.microsoft.com/en-US/library/windows/desktop/ms684175(v=vs.85).aspx

typedef void* (*MYFUNC)(int num1 = 1, int num2 = 2);

dll should export stdcall functions (there are different options but stdcall is "most standard") so
- make it stdcall in dll (and recompile dll if needed);
- use

typedef void* stdcall (*MYFUNC)(int num1 = 1, int num2 = 2);

MYFUNC UseMyFunctionX = (MYFUNC)
GetProcAddress(hModule, "_myFunctionName@10");

Use real name "myFunctionName" (without number @10).
Also use

tdump my.dll

and check what actual name you need to use (with underscore or without it).

Check result according to
GetProcAddress
https://msdn.microsoft.com/en-US/library/windows/desktop/ms683212(v=vs.85).aspx

Also you can export functions from dll as __declspec(dllexport) and use them as __declspec(dllimport).
Examplle from one of my projects:

//-----------------------------------------------------------------------------
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the WD7USB_EXPORTS
// symbol defined on the command line.

or in dll project's options

// this symbol should not be defined on any project
// that uses this DLL.

i.e in your application this symbol is undefined. So

// This way any other project whose source files include this file see
// WD7USB_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef WD7USB_EXPORTS
#define WD7USB_API __declspec(dllexport)
#else
#define WD7USB_API __declspec(dllimport)
#endif
//-----------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif

DWORD WD7USB_API WD7USB_OpenDevice(WD7USB_HANDLE* pDevice, WORD VendorId=0, WORD ProductId=0,
WD7USB_ATTACH_CALLBACK uacbf=NULL, int Timeout=DEFAULT_ATTACH_TIMEOUT);

VOID WD7USB_API WD7USB_CloseDevice(WD7USB_HANDLE* Device);
DWORD WD7USB_API WD7USB_BulkWrite(const WD7USB_HANDLE* pDevice, const void* Buffer, DWORD BufSize, DWORD Pipe=0x02,
DWORD Timeout=DEFAULT_TRANSFER_TIMEOUT);

DWORD WD7USB_API WD7USB_BulkRead(const WD7USB_HANDLE* pDevice, const void* Buffer, DWORD BufSize, DWORD* BytesTransferred,
DWORD Pipe=0x82, DWORD Timeout=DEFAULT_TRANSFER_TIMEOUT);

#ifdef __cplusplus
};

--
Alex

Edited by: Alex Belo on Jan 21, 2018 8:51 PM
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 21, 2018 10:24 AM   in response to: Alex Belo in response to: Alex Belo
Use real name "myFunctionName" (without number @10).
I don't now why it's the output name,

here's the .dll code
//
///********************************************
///to be compiled from vc12 also...
///The mycppcall.CPP to be 'mycppdialdll.dll'
///
#include "stdafx.h"
 
namespace nc
{
	
	///NumberCaller is a Class from an external DLL(not mine)  
	///Imports from (Originaldll.DLL that was compiled from vc12 too)
 
        //seen result function name is: _Create_NumberCaller@12
	I_API NumberCaller* __stdcall Create_NumberCaller(int dial1, double dial2)
	{
		Ptr<NumberCaller> zyx = createNumberCaller(dial1, dial2);
		zyx.addref();
		return zyx;
	}
 
	//seen result function name is: _NumberCallerLoad@8
	I_API void __stdcall NumberCallerLoad(NumberCaller* x, char* fn)
	{
		return x->load(fn);
	};
	
	//seen result function name is: _NumberCallerSave@8
	I_API void __stdcall NumberCallerSave(NumberCaller* y, char* fn)
	{
		return y->save(fn);
	};
 
	//seen result function name is: _DestroyNumberCaller@4
	I_API void __stdcall DestroyNumberCaller(NumberCaller* z)
	{
		//soon to be
	};
}
 
 
 
///********************************************
///The FILE stdafx.h
///
#pragma once
#define WIN32_LEAN_AND_MEAN 
#define I_API extern "C" __declspec(dllexport) 
 
#include <windows.h>
#include "dial.hpp"
#include "number.hpp"
 
 
 
///********************************************
///The FILE maindll.cpp
///
#include "stdafx.h"
 
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  reason,
                       LPVOID lpReserved
					 )
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}
//
 


here's the delphi code:
///
///********************************************
///********************************************
///DELPHI CODES that want to use the .DLL result compiled from vc12 'The mycppcall.CPP'
///********************************************
///********************************************
///This codes called from Delphi:(Full Code),
///Which I'm trying to port from Delphi TO C++Builder
///
unit unumbercaller;
 
interface
 
//Uses inputoutputcalls;
 
const
  dbldial = 1000.1;
  mycppdialdll = 'mycppdialdll.dll';
 
type
  TArrayOfInteger = Array of integer;//soon to used
 
  xCommon = class(TInterfacedObject)
  protected
    xdata: Pointer;
  public
    constructor Create(const ydata: Pointer);
end;
 
INumberCaller = interface
    procedure save(const fn: string);
    procedure load(const fn: string);
end;
 
TNumberCaller = class(xCommon, INumberCaller)
  public
    constructor createNumberCaller(dial1: Integer = 0; dial2: double = dbldial);
    procedure load(const fn: string);
    procedure save(const fn: string);
    destructor Destroy; override;
  end;
 
implementation
 
constructor xCommon.Create(const ydata: Pointer);
begin
  xdata := ydata;
end;
 
function xCreate_NumberCaller(dial1: Integer = 1; dial2: double = dbldial): Pointer; stdcall;
external mycppdialdll name '_Create_NumberCaller@12';
 
procedure NumberCallerLoad(const x: Pointer; fn: PAnsiChar); stdcall;
external mycppdialdll name '_NumberCallerLoad@8';
 
procedure NumberCallerSave(const x: Pointer; fn: PAnsiChar); stdcall;
external mycppdialdll name '_NumberCallerSave@8';
 
procedure DestroyNumberCaller(const x: Pointer); stdcall;
external mycppdialdll name '_DestroyNumberCaller@4';
 
 
{ TNumberCaller }
constructor TNumberCaller.createNumberCaller(dial1:integer; dial2:double);
begin
  inherited Create(xCreate_NumberCaller(dial1, dial2));
end;
 
procedure TNumberCaller.load(const fn: string);
begin
  NumberCallerLoad(xdata, pAnsiChar(AnsiString(fn)));
end;
 
procedure TNumberCaller.save(const fn: string);
begin
  NumberCallerSave(xdata, pAnsiChar(AnsiString(fn)));
end;
 
destructor TNumberCaller.Destroy;
begin
  if Assigned(xdata) then
  begin
    DestroyNumberCaller(xdata);
    xdata := nil;
  end;
  inherited;
end;
 
end.
 
 
///********************************************
///THE main Delphi code is:
///
unit Unit1p;
 
interface
 
uses
  unumbercaller,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
 
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  callerid  : INumberCaller;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
callerid  := TNumberCaller.createNumberCaller(1,101.1);
//
callerid.load('callerfilenamebackup1.xlsx');
//
callerid.save('callerfilenamebackup2.xlsx');
//
 
end;
 
end.
 


//
///
////
/////
Please show me where to changed that so the output function name will not have @12 or @number?
/////
////
///
//

Added source code file of C++ Builder ported from Delphi
///
///This FILE is unumbercaller.CPP
///
#include <vcl.h>
#pragma hdrstop
 
#include <System.hpp>
 
#include "unumbercaller.h"
 
//not using... no sure of this
/*
__fastcall TNumberCaller::TNumberCaller( const void* ydata )
{
inherited::xdata = &ydata;
}
*/
 
__fastcall xCommon::Create( const void *ydata )
{
xdata = &ydata;
}
 
HMODULE hModule = LoadLibrary(TEXT("mycppdialdll.dll"));
 
// NOT working...
//
//extern "C" __declspec(dllimport) /*# mycppdialdll name "_Create_NumberCaller@12" */ 
//void* __stdcall xCreate_NumberCaller( int dial1 = 1, double dial2 = dbldial );
//
 
//
// WORKING BUT errors came out..during run-time, 
// error message is "Access Violation....write of Address", sometimes error "Privileged Error"
//
typedef void* (*NCC)(int dial1 = 0, double dial2 = dbldial);
NCC xCreate_NumberCaller = (NCC) GetProcAddress(hModule, "_Create_NumberCaller@12");
 
 
// NOT working...
//
//extern "C" __declspec(dllimport) /*# mycppdialdll name "_NumberCallerLoad@8" */ 
//void __stdcall NumberCallerLoad( const void* x, char* fn);
//
//extern "C" __declspec(dllimport) /*# mycppdialdll name "_NumberCallerSave@8" */ 
//void __stdcall NumberCallerSave( const void* x, char* fn);
 
 
//
// WORKING BUT errors came out..during run-time, 
// error message is "Access Violation....write of Address", sometimes error "Privileged Error"
//
typedef void (*NCL)(const void* x, char* fn);
NCL NumberCallerLoad = (NCL) GetProcAddress(hModule, "_NumberCallerLoad@8");
 
typedef void (*NCS)(const void* x, char* fn);
NCS NumberCallerSave = (NCS) GetProcAddress(hModule, "_NumberCallerSave@8");
 
typedef void (*NCD)(const void* x);
NCD DestroyNumberCaller = (NCD) GetProcAddress(hModule, "_DestroyNumberCaller@4");
 
 
 
/* TNumberCaller */
__fastcall TNumberCaller::createNumberCaller( int dial1, double dial2 )
{
return Create( xCreate_NumberCaller( dial1, dial2 ));
}
 
void __fastcall TNumberCaller::load( const String fn)
{
  NumberCallerLoad( xdata, ((AnsiString) fn).c_str());
}
 
void __fastcall TNumberCaller::save( const String fn)
{
  NumberCallerSave( xdata, ((AnsiString) fn).c_str());
}
 
__fastcall TNumberCaller::~TNumberCaller( )
{
  if (( xdata != NULL ) )
  {
	DestroyNumberCaller( xdata );
	xdata = NULL;
  }
}
//

//
//
///This FILE is unumbercaller.h
///
#include <System.hpp>
#include "inputoutputcaller.h"
 
const double dbldial = 1000.1;
 
typedef DynamicArray< int > ArrayOfInteger;//soon to be used
 
class xCommon: TInterfacedObject {
  typedef TInterfacedObject inherited;
  friend class TNumberCaller;
  protected:
  	void* xdata;
  public:
  	virtual __fastcall Create( const void* ydata );
};
 
__interface INumberCaller {
  public:
  virtual void __fastcall save( const String fn ) = 0;
  virtual void __fastcall load( const String fn ) = 0;
};
 
 
class TNumberCaller: public xCommon, public INumberCaller {
  typedef xCommon inherited;
  friend class xCommon;
  public:
  __fastcall createNumberCaller( int dial1 = 1, double dial2 = dbldial );
  void __fastcall save( const String fn);
  void __fastcall load( const String fn);
 
  __fastcall virtual ~TNumberCaller( );
 
  //not using... no sure of this
  //public:
  //__fastcall TNumberCaller(const void* ydata );
 
};
//
//

//
//
///********************************************
///The main form of c++ builder numbercaller
///
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
#include <windows.h>
#include <system.hpp>
 
#pragma package(smart_init)
#pragma resource "*.dfm"
 
//#pragma comment(lib,"mycppdialdll.lib") //i don't know if useful
 
#include "unumbercaller.cpp" // the file that calls the mycppdialdll.dll
 
 
TForm1 *Form1;
 
INumberCaller *callerid; // inumbercaller
 
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
//
}
 
void __fastcall TForm1::FormCreate(TObject *Sender)
{
//
callerid = new TNumberCaller(); // new tnumbercaller
//
 
//testing...
TNumberCaller *tnc = new TNumberCaller();
 
// This is where the ERROR cause during run-time,
//I don't know what's wrong in the line of codes
//Error Message was "Access Violation...Write of Address..."
tnc->createNumberCaller(1,100.1);
//
//
}
 


p.s
If I ran the Delphi codes, it process correctly with no problems at all.
Alex Belo

Posts: 626
Registered: 10/8/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 22, 2018 10:37 AM   in response to: roca robin in response to: roca robin
roca robin wrote:

Use real name "myFunctionName" (without number @10).
I don't now why it's the output name,

(I'm rarely deal with dlls writing so I'm leaning with you right now or
recall something forgotten ;-))

here's the .dll code

///********************************************
///to be compiled from vc12 also...
///The mycppcall.CPP to be 'mycppdialdll.dll'
///
#include "stdafx.h"

namespace nc
{

Better export pure C functions (do not use namespace).

///NumberCaller is a Class from an external DLL(not mine)
///Imports from (Originaldll.DLL that was compiled from vc12 too)

//seen result function name is: _Create_NumberCaller@12


__stdcall
https://docs.microsoft.com/en-US/cpp/cpp/stdcall

The __stdcall calling convention is used to call Win32 API functions.
...
Name-decoration convention
An underscore (_) is prefixed to the name. The name is followed by the
at sign (@) followed by the number of bytes (in decimal) in the
argument list. Therefore, the function declared as int func( int a,
double b ) is decorated as follows: _func@12


@ is not legal char in C/C++ names. So to prevent exporting such
strange names we can use


Exporting C++ Functions for Use in C-Language Executables
https://docs.microsoft.com/en-us/cpp/build/exporting-cpp-functions-for-use-in-c-language-executables

If you have functions in a DLL written in C++ that you want to access
from a C-language module, you should declare these functions with C
linkage instead of C++ linkage. Unless otherwise specified, the C++
compiler uses C++ type-safe naming (also known as name decoration) and
C++ calling conventions, which can be difficult to call from C.
To specify C linkage, specify extern "C" for your function
declarations. For example:

extern "C" __declspec( dllexport ) int MyFunc(long parm1);

Exporting as extern "C" makes exported functions similar to Win API
functions so they can be used with all development tools.


I think it would be better to use proper interface for your dll:

mydll.h


#ifndef MYDLLH
#define MYDLLH

#ifdef MYDLL_EXPORTS
#define I_API extern "C" __declspec(dllexport)
#else
#define I_API extern "C" __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

I_API NumberCaller* __stdcall Create_NumberCaller
(int dial1, double dial2);

I_API void __stdcall NumberCallerLoad(NumberCaller* x, char* fn);

// etc.

#ifdef __cplusplus
} // extern "C"
#endif

#endif // MYDLLH


Now you can include this header
- in dll's C++ source file (where MYDLL_EXPORTS is defined somewhre;
project's options global defines is good choice);
- in your app C++ source file (where MYDLL_EXPORTS is not defined).

This header guarantee that interface will be the same on both sides.

I_API NumberCaller* __stdcall Create_NumberCaller
(int dial1, double dial2)
{
Ptr<NumberCaller> zyx = createNumberCaller(dial1, dial2);
zyx.addref();
return zyx;
}

//seen result function name is: _NumberCallerLoad@8
I_API void __stdcall NumberCallerLoad(NumberCaller* x, char* fn)
{
return x->load(fn);

How procedure (function which returns void, i.e. nothing) can return
some value? Compiler should generate an error (or warning at least).

};

//seen result function name is: _NumberCallerSave@8
I_API void __stdcall NumberCallerSave(NumberCaller* y, char* fn)
{
return y->save(fn);

the same here.

};

//seen result function name is: _DestroyNumberCaller@4
I_API void __stdcall DestroyNumberCaller(NumberCaller* z)
{
//soon to be
};
}

///********************************************
///The FILE stdafx.h
///
#pragma once
#define WIN32_LEAN_AND_MEAN
#define I_API extern "C" __declspec(dllexport)

#include <windows.h>
#include "dial.hpp"
#include "number.hpp"

///********************************************
///The FILE maindll.cpp
///
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD reason,
LPVOID lpReserved
)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
//

OK.

here's the delphi code:
///
///********************************************
///********************************************
///DELPHI CODES that want to use the .DLL result compiled from vc12
'The mycppcall.CPP'
///********************************************
///********************************************
///This codes called from Delphi:(Full Code),
///Which I'm trying to port from Delphi TO C++Builder
///
unit unumbercaller;

interface

//Uses inputoutputcalls;

const
dbldial = 1000.1;
mycppdialdll = 'mycppdialdll.dll';

type
TArrayOfInteger = Array of integer;//soon to used

xCommon = class(TInterfacedObject)
protected
xdata: Pointer;
public
constructor Create(const ydata: Pointer);
end;

INumberCaller = interface
procedure save(const fn: string);
procedure load(const fn: string);
end;

TNumberCaller = class(xCommon, INumberCaller)
public
constructor createNumberCaller(dial1: Integer = 0; dial2: double
= dbldial);
procedure load(const fn: string);
procedure save(const fn: string);
destructor Destroy; override;
end;

implementation

constructor xCommon.Create(const ydata: Pointer);
begin
xdata := ydata;
end;

function xCreate_NumberCaller(dial1: Integer = 1; dial2: double =
dbldial): Pointer; stdcall; external mycppdialdll name
'_Create_NumberCaller@12';

It seems Delphi use decorated names easily.
I have no idea how to use them in C.

procedure NumberCallerLoad(const x: Pointer; fn: PAnsiChar); stdcall;
external mycppdialdll name '_NumberCallerLoad@8';

procedure NumberCallerSave(const x: Pointer; fn: PAnsiChar); stdcall;
external mycppdialdll name '_NumberCallerSave@8';

procedure DestroyNumberCaller(const x: Pointer); stdcall;
external mycppdialdll name '_DestroyNumberCaller@4';

{ TNumberCaller }
constructor TNumberCaller.createNumberCaller(dial1:integer;
dial2:double); begin
inherited Create(xCreate_NumberCaller(dial1, dial2));
end;

procedure TNumberCaller.load(const fn: string);
begin
NumberCallerLoad(xdata, pAnsiChar(AnsiString(fn)));
end;

procedure TNumberCaller.save(const fn: string);
begin
NumberCallerSave(xdata, pAnsiChar(AnsiString(fn)));
end;

destructor TNumberCaller.Destroy;
begin
if Assigned(xdata) then
begin
DestroyNumberCaller(xdata);
xdata := nil;
end;
inherited;
end;

end.

OK.

...

Please show me where to changed that so the output function name will
not have @12 or @number?

AFAIUI You need to use 'extern "C"' as described above.

Added source code file of C++ Builder ported from Delphi
{code}
///
///This FILE is unumbercaller.CPP
///
#include <vcl.h>
#pragma hdrstop

#include <System.hpp>

#include "unumbercaller.h"

//not using... no sure of this
/*
__fastcall TNumberCaller::TNumberCaller( const void* ydata )
{
inherited::xdata = &ydata;

There is no "inherited" keyword in C++. Simply use xdata from parent
class if it is visible in successor.

}
*/

__fastcall xCommon::Create( const void *ydata )
{
xdata = &ydata;
}

HMODULE hModule = LoadLibrary(TEXT("mycppdialdll.dll"));

Check hModule here (as I suggested in my previous post).

You can also use static linking (lib file) instead of manual loading of
the dll.

// NOT working...
//
//extern "C" __declspec(dllimport)
/*# mycppdialdll name "_Create_NumberCaller@12" */
// void __stdcall xCreate_NumberCaller
(int dial1 = 1, double dial2 = dbldial );

What does it mean "NOT working..."? Compilation error? Or what?

// WORKING BUT errors came out..during run-time,
// error message is "Access Violation....write of Address", sometimes
error "Privileged Error"
//
typedef void* (*NCC)(int dial1 = 0, double dial2 = dbldial);

This typedef is not the same as

I_API NumberCaller* __stdcall Create_NumberCaller

in dll: there is no __stdcall !

Result is crash as expected !

NCC xCreate_NumberCaller = (NCC) GetProcAddress(hModule,
"_Create_NumberCaller@12");

Check returned value here (as I suggested in my previous post).

// NOT working...
//
//extern "C" __declspec(dllimport)
// /*# mycppdialdll name "_NumberCallerLoad@8" */
//void __stdcall NumberCallerLoad( const void* x, char* fn);
//
//extern "C" __declspec(dllimport)
/*# mycppdialdll name "_NumberCallerSave@8" */
//void __stdcall NumberCallerSave( const void* x, char* fn);

//
// WORKING BUT errors came out..during run-time,
// error message is "Access Violation....write of Address", sometimes
error "Privileged Error" //
typedef void (*NCL)(const void* x, char* fn);

The same here: calling convention does not matching to dll function.

etc.

p.s
If I ran the Delphi codes, it process correctly with no problems at
all.

It's because of correct calling convention (stdcall) defined in Delphi
code.

Hope this helps somehow. :-)
--
Alex
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 21, 2018 10:14 PM   in response to: Alex Belo in response to: Alex Belo
Edited and tested, Delphi codes run correctly,
C++ Builder compiles with no Error But during run-time error comes out.

Can you take a look of the c++ builder codes,
or including the vc12 few lines of code that won't end a @number function name?

I think server error again....

but anyway, I think your answers are right, I'll just follow your lead,

thank you so much, till next :D

Edited by: roca robin on Jan 22, 2018 2:47 PM

and lastly...I find Delphi as the most effective way of software development and programming....But I hate it when the world don't know it, all are c++ lovers so I changed for the better.

the language that I laugh is python! how in the world of programmers delphi was beaten by this snake!

but anyway we follow the stupidity of others, because the most stupid is the most popular. lol

thanks Alex, glad you came back

Edited by: roca robin on Jan 22, 2018 2:51 PM

Alex Belo

Posts: 626
Registered: 10/8/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 22, 2018 6:40 PM   in response to: roca robin in response to: roca robin
roca robin wrote:

I find Delphi as the most effective way of software
development and programming....But I hate it when the world don't
know it, all are c++ lovers

This is partially historical and partially technical issue:
- C is very old language
- it is strict (in most cases)
- it provides very detailed specifications of many things, so
- it is standard: all good vendors provide C-interface and
- it is portable (from microcontrollers without OS to supercomputers
with various OSs).

Delphi is really good because it was created deliberately to simplify
many tasks which are hard-to-use. But
- C was standard by then (a lot of code in the world) and
- Delphi was not portable at all.

--
Alex
Ted Lyngmo

Posts: 117
Registered: 10/3/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 23, 2018 6:22 AM   in response to: roca robin in response to: roca robin
roca robin wrote:
Edited and tested, Delphi codes run correctly,
C++ Builder compiles with no Error But during run-time error comes out.

If you've exported the functions as suggested, perhaps you could put the loading of the DLL etc. in a wrapper class and see if you get any exceptions. I usually find that helpful in similar situations. Example (untested):

dll.hpp
#ifndef _DLLWRAPPER_
#define _DLLWRAPPER_
 
#include <windows.h>
#include <string>
#include <Exception>
 
class EDllError : public Exception {
public:
    EDllError(const System::UnicodeString& error);
};
 
class DLL {
private:
    System::UnicodeString name;
    HMODULE dll;
public:
    DLL(const LPCTSTR lpLibFileName=NULL);               // default constructor
    virtual ~DLL();                                      // destructor
 
    DLL(const DLL& other) = delete;                      // copy constructor
    DLL(DLL&& other);                                    // move constructor
 
    DLL& operator=(const DLL& other) = delete;           // copy assignment
    DLL& operator=(DLL&& other);                         // move assignment
 
    void LoadLibrary(const LPCTSTR lpLibFileName);
    void FreeLibrary();
    FARPROC WINAPI GetProcAddress(LPCSTR lpProcName) const;
    void GetProcAddress(FARPROC& var, const LPCSTR lpProcName);
};
 
#endif


dll.cpp
#include "dll.hpp"
 
EDllError::EDllError(const System::UnicodeString& error) : Exception(error.c_str()) {}
 
DLL::DLL(const LPCTSTR lpLibFileName) : name(lpLibFileName) {
    if(lpLibFileName)
        this->LoadLibrary(lpLibFileName);
}
 
DLL::~DLL() {
    this->FreeLibrary();
}
 
DLL::DLL(DLL&& other) {
    name = std::move(other.name);
    dll = other.dll;
    other.dll = NULL;
}
 
DLL& DLL::operator=(DLL&& other) {
    this->FreeLibrary();
    name = other.name;
    dll = other.dll;
    other.dll = NULL;
    return *this;
}
 
void DLL::LoadLibrary(const LPCTSTR lpLibFileName) {
    this->FreeLibrary();
    name = lpLibFileName;
    dll = ::LoadLibrary(lpLibFileName);
    if( dll == NULL )
        throw EDllError( System::UnicodeString("Can't load ")+lpLibFileName );
}
 
void DLL::FreeLibrary() {
    if(dll) {
        ::FreeLibrary(dll);
        dll = NULL;
    }
}
 
FARPROC WINAPI DLL::GetProcAddress(const LPCSTR lpProcName) const {
    return ::GetProcAddress(dll, lpProcName);
}
 
void DLL::GetProcAddress(FARPROC& var, const LPCSTR lpProcName) {
    var = this->GetProcAddress(lpProcName);
    if( var == NULL )
        throw EDllError( name + TEXT(" is missing ")+lpProcName+TEXT("()") );
}


And then your usage:

mycppdialdll.hpp
#ifndef _MYCPPDIALDLL_
#define _MYCPPDIALDLL_
 
#include "dll.hpp"
 
class MyCppDialDLL : public DLL {
    typedef void* (WINAPI *NCC)(int, double);
    typedef void (WINAPI *NCLS)(const void*, char*);
    typedef void (WINAPI *NCD)(const void*);
public:
    NCC  Create_NumberCaller;
    NCLS NumberCallerLoad;
    NCLS NumberCallerSave;
    NCD  DestroyNumberCaller;
 
    MyCppDialDLL();
};
 
#endif


mycppdialdll.cpp
#include "mycppdialdll.hpp"
 
MyCppDialDLL::MyCppDialDLL() : DLL(TEXT("mycppdialdll.dll")) {
    GetProcAddress( (FARPROC&) Create_NumberCaller, "Create_NumberCaller");
    GetProcAddress( (FARPROC&) NumberCallerLoad, "NumberCallerLoad");
    GetProcAddress( (FARPROC&) NumberCallerSave, "NumberCallerSave");
    GetProcAddress( (FARPROC&) DestroyNumberCaller, "DestroyNumberCaller");
}


And in your form (or similar):
#include "mycppdialdll.hpp"
 
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
        MyCppDialDLL dialer;
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};


Then, in your application code:
    void* nc = dialer.Create_NumberCaller( <some_int>, <some_double> );
    dialer.NumberCallerLoad( nc, "someting");
    ...


Br,
Ted
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 23, 2018 9:42 AM   in response to: Ted Lyngmo in response to: Ted Lyngmo
Ted Lyngmo wrote:
roca robin wrote:
Edited and tested, Delphi codes run correctly,
C++ Builder compiles with no Error But during run-time error comes out.

If you've exported the functions as suggested, perhaps you could put the loading of the DLL etc. in a wrapper class and see if you get any exceptions. I usually find that helpful in similar situations. Example (untested):

dll.hpp
#ifndef _DLLWRAPPER_
#define _DLLWRAPPER_
 
#include <windows.h>
#include <string>
#include <Exception>
 
class EDllError : public Exception {
public:
    EDllError(const System::UnicodeString& error);
};
 
class DLL {
private:
    System::UnicodeString name;
    HMODULE dll;
public:
    DLL(const LPCTSTR lpLibFileName=NULL);               // default constructor
    virtual ~DLL();                                      // destructor
 
    DLL(const DLL& other) = delete;                      // copy constructor
    DLL(DLL&& other);                                    // move constructor
 
    DLL& operator=(const DLL& other) = delete;           // copy assignment
    DLL& operator=(DLL&& other);                         // move assignment
 
    void LoadLibrary(const LPCTSTR lpLibFileName);
    void FreeLibrary();
    FARPROC WINAPI GetProcAddress(LPCSTR lpProcName) const;
    void GetProcAddress(FARPROC& var, const LPCSTR lpProcName);
};
 
#endif


dll.cpp
#include "dll.hpp"
 
EDllError::EDllError(const System::UnicodeString& error) : Exception(error.c_str()) {}
 
DLL::DLL(const LPCTSTR lpLibFileName) : name(lpLibFileName) {
    if(lpLibFileName)
        this->LoadLibrary(lpLibFileName);
}
 
DLL::~DLL() {
    this->FreeLibrary();
}
 
DLL::DLL(DLL&& other) {
    name = std::move(other.name);
    dll = other.dll;
    other.dll = NULL;
}
 
DLL& DLL::operator=(DLL&& other) {
    this->FreeLibrary();
    name = other.name;
    dll = other.dll;
    other.dll = NULL;
    return *this;
}
 
void DLL::LoadLibrary(const LPCTSTR lpLibFileName) {
    this->FreeLibrary();
    name = lpLibFileName;
    dll = ::LoadLibrary(lpLibFileName);
    if( dll == NULL )
        throw EDllError( System::UnicodeString("Can't load ")+lpLibFileName );
}
 
void DLL::FreeLibrary() {
    if(dll) {
        ::FreeLibrary(dll);
        dll = NULL;
    }
}
 
FARPROC WINAPI DLL::GetProcAddress(const LPCSTR lpProcName) const {
    return ::GetProcAddress(dll, lpProcName);
}
 
void DLL::GetProcAddress(FARPROC& var, const LPCSTR lpProcName) {
    var = this->GetProcAddress(lpProcName);
    if( var == NULL )
        throw EDllError( name + TEXT(" is missing ")+lpProcName+TEXT("()") );
}


And then your usage:

mycppdialdll.hpp
#ifndef _MYCPPDIALDLL_
#define _MYCPPDIALDLL_
 
#include "dll.hpp"
 
class MyCppDialDLL : public DLL {
    typedef void* (WINAPI *NCC)(int, double);
    typedef void (WINAPI *NCLS)(const void*, char*);
    typedef void (WINAPI *NCD)(const void*);
public:
    NCC  Create_NumberCaller;
    NCLS NumberCallerLoad;
    NCLS NumberCallerSave;
    NCD  DestroyNumberCaller;
 
    MyCppDialDLL();
};
 
#endif


mycppdialdll.cpp
#include "mycppdialdll.hpp"
 
MyCppDialDLL::MyCppDialDLL() : DLL(TEXT("mycppdialdll.dll")) {
    GetProcAddress( (FARPROC&) Create_NumberCaller, "Create_NumberCaller");
    GetProcAddress( (FARPROC&) NumberCallerLoad, "NumberCallerLoad");
    GetProcAddress( (FARPROC&) NumberCallerSave, "NumberCallerSave");
    GetProcAddress( (FARPROC&) DestroyNumberCaller, "DestroyNumberCaller");
}


And in your form (or similar):
#include "mycppdialdll.hpp"
 
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
        MyCppDialDLL dialer;
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};


Then, in your application code:
    void* nc = dialer.Create_NumberCaller( <some_int>, <some_double> );
    dialer.NumberCallerLoad( nc, "someting");
    ...


Br,
Ted

Ted, I will try your suggestions, and Alex some of your thoughts I think it's better,

thank you both,
try to...soon...
I'm on business trip.....

message something soon...

roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 25, 2018 7:23 AM   in response to: roca robin in response to: roca robin
@Ted Lyngmo

The looks nicer and newer for me, but I used __stdcall as Alex suggested,
extern "C" __declspec(dllimport) void* __stdcall Create_NumberCaller( int dial1 = 1, double dial2 = dbldial );

I've forgotten to included the lib file
#pragma comment(lib,"mycppdialdll.lib")

The only problem left is,
Improper use of typedef 'TNumberCaller'
in this line of code,
callerid = TNumberCaller->createNumberCaller(1,100.1);

this is the whole code I used, I don't know where is wrong,

///********************************************
///The main form of c++ builder numbercaller
///
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
#include <windows.h>
#include <system.hpp>
 
#pragma package(smart_init)
#pragma resource "*.dfm"
 
#pragma comment(lib,"mycppdialdll.lib")
 
#include "unumbercaller.cpp" 
 
 
TForm1 *Form1;
 
INumberCaller *callerid;
 
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
//
}
 
void __fastcall TForm1::FormCreate(TObject *Sender)
{
//
//
 
//WITH THIS 2 LINES, I can know that __stdcall is working, calling "mycppdialdll.dll"
TNumberCaller *tnumd = new TNumberCaller();
tnumd->createNumberCaller(1,100.1);
//
ShowMessage("Test_1");
//
callerid = TNumberCaller->createNumberCaller(1,100.1);  >>>>>>>>>> //line ERROR > Improper use of typedef TNumberCaller'
//
ShowMessage("Test_2");
//
//
}

//
///
///This FILE is unumbercaller.CPP
///
#include <vcl.h>
#pragma hdrstop
 
#include <System.hpp>
 
#include "unumbercaller.h"
 
 
//not using... no sure of this
/*
__fastcall TNumberCaller::TNumberCaller( const void* ydata )
{
xdata = &ydata;
}
*/
 
__fastcall xCommon::Create( const void *ydata )
{
xdata = &ydata;
}
 
extern "C" __declspec(dllimport) void* __stdcall Create_NumberCaller( int dial1 = 1, double dial2 = dbldial );
extern "C" __declspec(dllimport) void __stdcall NumberCallerLoad(const void* x, char* fn);
extern "C" __declspec(dllimport) void __stdcall NumberCallerSave(const void* x, char* fn);
extern "C" __declspec(dllimport) void __stdcall DestroyNumberCaller(const void* x); 
 
 
/* TNumberCaller */
__fastcall TNumberCaller::createNumberCaller( int dial1, double dial2 )
{
return Create(Create_NumberCaller( dial1, dial2 ));
}
 
void __fastcall TNumberCaller::load( const String fn)
{
  NumberCallerLoad( xdata, ((AnsiString) fn).c_str());
}
 
void __fastcall TNumberCaller::save( const String fn)
{
  NumberCallerSave( xdata, ((AnsiString) fn).c_str());
}
 
__fastcall TNumberCaller::~TNumberCaller( )
{
  if (( xdata != NULL ) )
  {
	DestroyNumberCaller( xdata );
	xdata = NULL;
  }
}
//

//
//
//
///This FILE is unumbercaller.h
///
#include <System.hpp>
#include "inputoutputcaller.h"
 
const double dbldial = 10000.1;
 
class TNumberCaller;
class xCommon;
 
typedef DynamicArray< int > ArrayOfInteger;//soon to be used
 
class xCommon: TInterfacedObject {
  typedef TInterfacedObject inherited;
  friend class TNumberCaller;
  protected:
  	void* xdata;
  public:
  	virtual __fastcall Create( const void* ydata );
};
 
__interface INumberCaller {
  public:
  virtual void __fastcall save( const String fn ) = 0;
  virtual void __fastcall load( const String fn ) = 0;
};
 
 
class TNumberCaller: public xCommon, public INumberCaller {
  typedef xCommon inherited;
  friend class xCommon;
  public:
  __fastcall createNumberCaller( int dial1 = 1, double dial2 = dbldial );
  void __fastcall save( const String fn);
  void __fastcall load( const String fn);
 
  __fastcall virtual ~TNumberCaller( );
 
  //not using... no sure of this
  //public:
  //__fastcall TNumberCaller(const void* ydata );
 
};
//
Ted Lyngmo

Posts: 117
Registered: 10/3/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 25, 2018 11:31 AM   in response to: roca robin in response to: roca robin
roca robin wrote:
@Ted Lyngmo

The looks nicer and newer for me, but I used __stdcall as Alex suggested,

https://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
"Standard calling convention (__stdcall)
This convention is usually used to call Win32 API functions. In fact, WINAPI is nothing but another name for __stdcall"

extern "C" __declspec(dllimport) void* __stdcall Create_NumberCaller( int dial1 = 1, double dial2 = dbldial );

I've forgotten to included the lib file
#pragma comment(lib,"mycppdialdll.lib")

I must say that I haven't read every line in this thread, but I assume mycppdialdll.lib is an import library and not a static library.

The only problem left is,
Improper use of typedef 'TNumberCaller'
in this line of code,
callerid = TNumberCaller->createNumberCaller(1,100.1);

TNumberCaller isn't an instance. "tnumd" is.

If you create a blank project and add the four files in my example + a copy of"mycppdialdll.dll" and in your "form1.h" add:

#include "mycppdialdll.hpp"

plus
private:	// User declarations
        MyCppDialDLL dialer;

and then compile and run, do you get an exception or a blank form?

If you get an exception, it should give you a hint. If not, chances are that the MyCppDialDLL instance "dialer" is working as-is, and you can then go ahead and create a small wrapper class containing one MyCppDialDLL that manages the resource allocated. Simple wrapper:

#include <stdexcept>
//...
class TNumberCaller {
private:
    MyCppDialDLL dialer;
    void* m_nc;
    void free_nc() {
        if(m_nc) dialer.DestroyNumberCaller(m_nc);
        m_nc = NULL;
    }
public:
    TNumberCaller( int dial1, double dial2=1000.1 ) :
        dialer(), m_nc(dialer.Create_NumberCaller(dial1, dial2))
    {
        if(m_nc==NULL) throw std::runtime_error("TNumberCaller could not be created");
    }
 
    TNumberCaller(TNumberCaller&& other) {
        dialer = std::move(other.dialer);
        m_nc = other.m_nc;
        other.m_nc = NULL;
    }
 
    TNumberCaller& operator=(TNumberCaller&& other) {
        free_nc();
        dialer = std::move(other.dialer);
        m_nc = other.m_nc;
        other.m_nc = NULL;
        return *this;
    }
 
    void load( const String& fn ) const {
        AnsiString conv(fn);
        dialer.NumberCallerLoad(m_nc, conv.c_str());
    }
 
    void save( const String& fn ) const {
        AnsiString conv(fn);
        dialer.NumberCallerSave(m_nc, conv.c_str());
    }
 
    virtual ~TNumberCaller() {
        free_nc();
    }
};


And somewhere in the code:
#include <memory>
 
    // this line could go into the forms protected: section if you want to keep
    // a number caller instance initiated with {1, 100.1} for as long as the form lives
 
    std::unique_ptr<TNumberCaller> tnumd = std::make_unique<TNumberCaller>(1,100.1);
 
    // somewhere ...
    tnumd->load( to_load ); // String
    tnumd->save( to_save ); // String


With that approach you don't need to have an import library available (nor do you need the #pragma comment(lib,"mycppdialdll.lib") part). You also don't need any of the "extern "C" __declspec(dllimport) ..." stuff. As long as you know the calling convension used in the DLL you should be able to use it and making a new DLL loader with the DLL class becomes pretty easy.

Br,
Ted

Edited by: Ted Lyngmo on Jan 25, 2018 12:04 PM - Made TNumberCaller movable

Edited by: Ted Lyngmo on Jan 29, 2018 1:26 AM - Added constructor exception.
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 25, 2018 12:21 PM   in response to: Ted Lyngmo in response to: Ted Lyngmo
I must say that I haven't read every line in this thread, but I assume mycppdialdll.lib is an import library and not a static library.

maybe I don't understand,

mycppdialdll.lib is from a command "coff2omf mycppdialdll.dll mycppdialdll"

the mycppdialdll.dll is compiled from vc12 and I think I understand from you that the file I'm making is a wrapper for the Main_original.DLL(compiled by other from vc12)

so mycppdialdll.dll is the file that I compiled from vc12(and I think that is called a wrapper of Main_original.DLL

After the command coff2omf I copy the .LIB file and use it under my folder....the file was "mycppdialdll.lib"

Frankly I learn from both of you, line by line, step by step, by reading your lines of codes slowly...

I'll write feedback soon as I have time to test the codes you send.

thank you

roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 25, 2018 10:34 PM   in response to: Ted Lyngmo in response to: Ted Lyngmo
With that approach you don't need to have an import library available (nor do you need the #pragma comment(lib,"mycppdialdll.lib") part). You also don't need any of the >"extern "C" __declspec(dllimport) ..." stuff. As long as you know the calling convension used in the DLL you should be able to use it and making a new DLL loader with the >DLL class becomes pretty easy.

I think your style of coding is only applicable for solid c++builder?
and that style is not applicable under vc12?

TNumberCaller isn't an instance. "tnumd" is.

Why in Delphi can be declared as: and this program codes in Delphi runs without issues.
///********************************************
///THE main Delphi code is:
///
unit Unit1p;
 
interface
 
uses
  unumbercaller,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
 
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  callerid  : INumberCaller;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
callerid  := TNumberCaller.createNumberCaller(1,101.1);
//
callerid.load('callerfilenamebackup1.xlsx');
//
callerid.save('callerfilenamebackup2.xlsx');
//
 
end;
 
end.


//

///
unit unumbercaller;
 
interface
 
//Uses inputoutputcalls;
 
const
  dbldial = 1000.1;
  mycppdialdll = 'mycppdialdll.dll';
 
type
  TArrayOfInteger = Array of integer;//soon to used
 
  xCommon = class(TInterfacedObject)
  protected
    xdata: Pointer;
  public
    constructor Create(const ydata: Pointer);
end;
 
INumberCaller = interface
    procedure save(const fn: string);
    procedure load(const fn: string);
end;
 
TNumberCaller = class(xCommon, INumberCaller)
  public
    constructor createNumberCaller(dial1: Integer = 0; dial2: double = dbldial);
    procedure load(const fn: string);
    procedure save(const fn: string);
    destructor Destroy; override;
  end;
 
implementation
 
constructor xCommon.Create(const ydata: Pointer);
begin
  xdata := ydata;
end;
 
function xCreate_NumberCaller(dial1: Integer = 1; dial2: double = dbldial): Pointer; stdcall;
external mycppdialdll name '_Create_NumberCaller@12';
 
procedure NumberCallerLoad(const x: Pointer; fn: PAnsiChar); stdcall;
external mycppdialdll name '_NumberCallerLoad@8';
 
procedure NumberCallerSave(const x: Pointer; fn: PAnsiChar); stdcall;
external mycppdialdll name '_NumberCallerSave@8';
 
procedure DestroyNumberCaller(const x: Pointer); stdcall;
external mycppdialdll name '_DestroyNumberCaller@4';
 
 
{ TNumberCaller }
constructor TNumberCaller.createNumberCaller(dial1:integer; dial2:double);
begin
  inherited Create(xCreate_NumberCaller(dial1, dial2));
end;
 
procedure TNumberCaller.load(const fn: string);
begin
  NumberCallerLoad(xdata, pAnsiChar(AnsiString(fn)));
end;
 
procedure TNumberCaller.save(const fn: string);
begin
  NumberCallerSave(xdata, pAnsiChar(AnsiString(fn)));
end;
 
destructor TNumberCaller.Destroy;
begin
  if Assigned(xdata) then
  begin
    DestroyNumberCaller(xdata);
    xdata := nil;
  end;
  inherited;
end;
 
end.
Ted Lyngmo

Posts: 117
Registered: 10/3/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 26, 2018 3:59 AM   in response to: roca robin in response to: roca robin
roca robin wrote:

maybe I don't understand,
mycppdialdll.lib is from a command "coff2omf mycppdialdll.dll mycppdialdll"
the mycppdialdll.dll is compiled from vc12 and I think I understand from you that the file I'm making is a wrapper for the Main_original.DLL(compiled by other from vc12)
so mycppdialdll.dll is the file that I compiled from vc12(and I think that is called a wrapper of Main_original.DLL

After the command coff2omf I copy the .LIB file and use it under my folder....the file was "mycppdialdll.lib"

I can't say that I'm very familiar with COFF2OMF.EXE (the Import Library Conversion Tool - I even had to look it up). I've used it (or some similar tool) on DLL:s long ago to get the DLL:s working in C++ Builder when the format wasn't one that could be used as-is with LoadLibrary and GetProcAddress. It sounds to me like the DLL (or is it DLL:s?) you're trying to use should be __stdcall / WINAPI DLL:s like most Windows DLL:s. If so, I'd use them as-is without creating import lib:s or having to clutter the code with __declspec:s etc.

Frankly I learn from both of you, line by line, step by step, by reading your lines of codes slowly...
I'll write feedback soon as I have time to test the codes you send.

Please do.

With that approach you don't need to have an import library available
(nor do you need the #pragma comment(lib,"mycppdialdll.lib") part).
You also don't need any of the >"extern "C" __declspec(dllimport) ..." stuff.
As long as you know the calling convension used in the DLL you should be
able to use it and making a new DLL loader with the >DLL class becomes pretty easy.

I think your style of coding is only applicable for solid c++builder?
and that style is not applicable under vc12?

Yes, the style works well, but I made the DLL base class a little C++ Builder aware to automatically throw exceptions that would show up nicely without you having add std:exception handlers and I perhaps used some C++ Builder specifics where I didn't need to.

Anyway, I though this was about using a DLL created with VS in C++ Builder? If you need the same code for loading the DLL in both VS and C++ Builder, it's pretty easy to make the DLL base class agnostic. The MyCppDialDLL should be working as is.
The final TNumberCaller wrapper only uses lazy string conversion via AnsiString to make it C++ Builder specific.

TNumberCaller isn't an instance. "tnumd" is.

Why in Delphi can be declared as: and this program codes in Delphi runs without issues.

I don't know Delphi but my guess is that declaring createNumberCaller the "constructor" for that class has something to do with it.

You don't call constructors like that in C++. You can create factory methods (static or not static) in addition to the constructor if you need to - but in this case, there's no need. You already have a working constructor.

Br,
Ted
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 26, 2018 7:47 AM   in response to: Ted Lyngmo in response to: Ted Lyngmo
Yes, the style works well, but I made the DLL base class a little C++ Builder aware to automatically throw exceptions that would show up nicely without you having add >>std:exception handlers and I perhaps used some C++ Builder specifics where I didn't need to.

@Ted, for now your coding style is in my mind, I will use it someday,,..
or maybe going to change my mind testing all your style,

thank you,
I don't intend to stay at c++ builder only, I also want to use vc12c++

Anyway, I though this was about using a DLL created with VS in C++ Builder? If you need the same code for loading the DLL in both VS and C++ Builder, it's pretty >>easy to make the DLL base class agnostic. The MyCppDialDLL should be working as is.
Ah...
The final TNumberCaller wrapper only uses lazy string conversion via AnsiString to make it C++ Builder specific.
Oh,,,
maybe I will understand this overall in times I will follow your coding style, I will some time I really need to understand everything about that.

but in this case, there's no need. You already have a working constructor.
you mean this code is already working? I can only test on Delphi, but not on c++ builder for now because my codes are still incomplete.
///********************************************
///The main form of c++ builder numbercaller
///
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
#include <windows.h>
#include <system.hpp>
 
#pragma package(smart_init)
#pragma resource "*.dfm"
 
#pragma comment(lib,"mycppdialdll.lib")
 
#include "unumbercaller.cpp" 
 
 
TForm1 *Form1;
 
INumberCaller *callerid;
String fn; 
 
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
//
}
 
void __fastcall TForm1::FormCreate(TObject *Sender)
{
//
//
 
//WITH THIS 2 LINES, I can know that __stdcall is working, calling "mycppdialdll.dll"
TNumberCaller *tnumd = new TNumberCaller();
tnumd->createNumberCaller(1,100.1); /// >>>>>> YOU MEAN THIS CODE LINE IS OK?
//
ShowMessage("Test_1");
//
//THIS IS LIKE DELPHI STYLE....
//callerid = TNumberCaller->createNumberCaller(1,100.1);  >>>>>>>>>> //line ERROR > Improper use of typedef TNumberCaller'
//
 
///What about if I used "tnumd->load" or "tnumd->save" will it carry the function?
tnumd->load(fn);
ShowMessage("Test_2");
//
//
}

I think in c++ builder INumberCaller is nothing if you say that I have already a working constructor code in c++ builder.

Ted Lyngmo

Posts: 117
Registered: 10/3/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 28, 2018 10:42 AM   in response to: roca robin in response to: roca robin
I just noticed that the actual DLL code seems to have a strange thing in it. I assume that Ptr is a smart pointer of some sort and it seems that you are tricking it to not delete the object when it goes out of scope by manually increasing the reference counter. That effectively makes the Ptr useless so you can just remove it. You also "return" from the void functions. Does that even compile?

Rewrite:
///The mycppcall.CPP to be 'mycppdialdll.dll'
///
#include "stdafx.h"
 
///NumberCaller is a Class from an external DLL(not mine)  
///Imports from (Originaldll.DLL that was compiled from vc12 too)
 
I_API NumberCaller* __stdcall Create_NumberCaller(int dial1, double dial2)
{
	return createNumberCaller(dial1, dial2);
} 
 
I_API void __stdcall NumberCallerLoad(NumberCaller* nc, char* fn)
{
	nc->load(fn);
};
	
I_API void __stdcall NumberCallerSave(NumberCaller* nc, char* fn)
{
	nc->save(fn);
};
 
I_API void __stdcall DestroyNumberCaller(NumberCaller* nc)
{
	delete nc;
};


but in this case, there's no need. You already have a working constructor.
you mean this code is already working?

What I meant was that you already have a constructor. You should use that one to create resource instead of exposing the Create_NumberCaller method and then use the destructor to call DestroyNumberCaller.

I can only test on Delphi, but not on c++ builder for now because my codes are still incomplete.
//WITH THIS 2 LINES, I can know that __stdcall is working, calling "mycppdialdll.dll"
TNumberCaller *tnumd = new TNumberCaller();
tnumd->createNumberCaller(1,100.1); /// >>>>>> YOU MEAN THIS CODE LINE IS OK?
No, the line above:
TNumberCaller *tnumd = new TNumberCaller();

If you look at my version of the TNumberCaller class you'll notice that constructing a TNumberCaller will also call Create_NumberCaller using the arguments given to the constructor, so you should be able to use it like this:
TNumberCaller *tnumd = new TNumberCaller(1, 100.1);
tnumb->load(fn);
tnumb->save(fn);
delete tnumd;

or preferably like this to avoid having to manually delete it:
std::unique_ptr<TNumberCaller> tnumd(new TNumberCaller(1, 100.1));
tnumb->load(fn);
tnumb->save(fn);


//THIS IS LIKE DELPHI STYLE....
//callerid = TNumberCaller->createNumberCaller(1,100.1); >>>>>>>>>> //line ERROR > Improper use of typedef TNumberCaller'

Yes, you are trying to use the class as a pointer to an instance of the class. That won't work.

///What about if I used "tnumd->load" or "tnumd->save" will it carry the function?
tnumd->load(fn);

I'm not sure I understand the question, but the code looks ok.

I think in c++ builder INumberCaller is nothing if you say that I have already a working constructor code in c++ builder.

Yes. It's not needed. Did you have any chance of trying out my suggestions?

Br,
Ted
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 29, 2018 12:01 AM   in response to: Ted Lyngmo in response to: Ted Lyngmo
@Ted,
I'll be reading back ALL of your suggestions, because I think it's more application like the Delphi version I have.

thank you,

message you back soon.
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 30, 2018 10:26 AM   in response to: Ted Lyngmo in response to: Ted Lyngmo
@Ted,
Please take a look again,
I'm lost with your coding style, well you show where and what should be written on this files?
please copy paste again your lines of code, I'm so confused.
please arrange according to the files I listed below ----->
p.S
I posted again the codes that I used,

//-----------------------------------------------------------//-----------------------------------------------------------
//
//-----------------------------------------------------------
//THIS FOLLOWING LINES BELOW OUTPUTS MYCPPDIALDLL.DLL
//-----------------------------------------------------------
//
//begin line of file 'mycppdialdll.dll' -----> What should I put here? v
//
//
///********************************************
///I compiled from vc12... I think this is a .DLL wrapper,,, Calls Complecated Original DLL ***
///This is also the .DLL that I used in Delphi that works good.***
//
//
#include "stdafx.h"

namespace nc
{

I_API NumberCaller* __stdcall Create_NumberCaller(int dial1, double dial2)
{
Ptr<NumberCaller> x = createNumberCaller(dial1, dial2);
x.addref();
return x;
}

I_API void __stdcall NumberCallerLoad(NumberCaller* x, char* fn)
{
return x->load(fn);
};

I_API void __stdcall NumberCallerSave(NumberCaller* x, char* fn)
{
return x->save(fn);
};

I_API void __stdcall DestroyNumberCaller(NumberCaller* x)
{
//soon to be
};
}
//
//end line of file

//


//begin line of file
//
///********************************************
//----------------------------------------------
///The FILE >>> stdafx.h <<<
//----------------------------------------------
///
#pragma once
#define WIN32_LEAN_AND_MEAN
#define I_API extern "C" __declspec(dllexport)

#include <windows.h>
//#include "dial.hpp"
//#include "number.hpp"
//
//end line of file

//


//begin line of file
//
///********************************************
//----------------------------------------------
///The FILE >>> maindll.cpp <<<
//----------------------------------------------
///
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD reason,
LPVOID lpReserved
)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
//
//end line of file


//
//-----------------------------------------------------------//-----------------------------------------------------------
//

//-----------------------------------------------------------
//THIS FOLLOWING LINES BELOW ARE USED IN C++ BUILDER ACTIVELY
//-----------------------------------------------------------
//
//begin line of file 'unumbercaller.h' -----> What should I put here? v
//
///
#include <System.hpp>
#include "inputoutputcaller.h"

const double dbldial = 1000.1;

typedef DynamicArray< int > ArrayOfInteger;//soon to be used

class xCommon: TInterfacedObject {
typedef TInterfacedObject inherited;
friend class TNumberCaller;
protected:
void* xdata;
public:
virtual __fastcall Create( const void* ydata );
};

__interface INumberCaller {
public:
virtual void __fastcall save( const String fn ) = 0;
virtual void __fastcall load( const String fn ) = 0;
};

class TNumberCaller: public xCommon, public INumberCaller {
typedef xCommon inherited;
friend class xCommon;
public:
__fastcall createNumberCaller( int dial1 = 1, double dial2 = dbldial );
void __fastcall save( const String fn);
void __fastcall load( const String fn);
__fastcall virtual ~TNumberCaller();
};
//
//end line of file


//


//
//begin line of file 'unumbercaller.cpp' -----> What should I put here? v
//
///
#include <vcl.h>
#pragma hdrstop

#include <System.hpp>

#include "unumbercaller.h" //<<< calling the header file

__fastcall xCommon::Create( const void *ydata )
{
xdata = &ydata;
}

extern "C" __declspec(dllimport) void* __stdcall Create_NumberCaller( int dial1 = 1, double dial2 = dbldial );
extern "C" __declspec(dllimport) void __stdcall NumberCallerLoad( const void* x, char* fn);
extern "C" __declspec(dllimport) void __stdcall NumberCallerSave( const void* x, char* fn);

/* TNumberCaller */
__fastcall TNumberCaller::createNumberCaller( int dial1, double dial2 )
{
return Create( Create_NumberCaller( dial1, dial2 ));
}

void __fastcall TNumberCaller::load( const String fn)
{
NumberCallerLoad( xdata, ((AnsiString) fn).c_str());
}

void __fastcall TNumberCaller::save( const String fn)
{
NumberCallerSave( xdata, ((AnsiString) fn).c_str());
}

__fastcall TNumberCaller::~TNumberCaller( )
{
if (( xdata != NULL ) )
{
DestroyNumberCaller( xdata );
xdata = NULL;
}
}
//
//end line of file

//


//
//-----------------------------------------------------------//-----------------------------------------------------------
//
///********************************************
///The main form of c++ builder numbercaller
///
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <windows.h>
#include <system.hpp>

#pragma package(smart_init)
#pragma resource "*.dfm"

#pragma comment(lib,"mycppdialdll.lib") //I used this LIB *** vc12 DLL(mycppdialdll.dll) converted to .LIB using coff2omf ***

#include "unumbercaller.cpp" // the file that calls the mycppdialdll.dll

TForm1 *Form1;

INumberCaller *callerid; // inumbercaller

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
//
//testing...

callerid = TNumberCaller->createNumberCaller(1,100.1); //This is the code structure I write in Delphi that runs good.

//
//
}

I'm sorry if I disturbed you but it seems in the beginning that you reply your coding style are c++ builder expertise.

Ted Lyngmo

Posts: 117
Registered: 10/3/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 31, 2018 12:51 PM   in response to: roca robin in response to: roca robin
Did you try to:
Rewrite the actual "mycppdialdll.dll" code like I suggested in https://forums.embarcadero.com/message.jspa?messageID=927919#927919 and recompile it?

Then,
1. Create a new blank project (to not have to destroy your work).
2. Copy only the newly compiled DLL "mycppdialdll.dll" to the new project directory.
3. Add the four files in https://forums.embarcadero.com/message.jspa?messageID=924586#924586 to the new project directory and add them to the project in C++ Builder.
4. Create a TNumberDialer class to use all the above - as the one I made in https://forums.embarcadero.com/message.jspa?messageID=927020#927020

The classes I wrote aren't perfect and can be reworked to work in both C++ Builder and Visual Studio - but if the DLL is __stdcall it should be loaded whenever you instantiate a TNumberDialer (the one I wrote as an example) - and you should be able to call the load() / save() methods (on the instance).

I_API NumberCaller* __stdcall Create_NumberCaller(int dial1, double dial2)
{
    Ptr<NumberCaller> x = createNumberCaller(dial1, dial2);
    x.addref();
    return x;
}
Why do you do the above instead of
I_API NumberCaller* __stdcall Create_NumberCaller(int dial1, double dial2)
{
    return createNumberCaller(dial1, dial2);
}

and why do you "return" from NumberCallerLoad and NumberCallerSave when the functions are "void"?

I_API void __stdcall DestroyNumberCaller(NumberCaller* x)
{
	//soon to be
};
Why not replace "// soon to be" with:
delete x;

//-----------------------------------------------------------
//THIS FOLLOWING LINES BELOW ARE USED IN C++ BUILDER ACTIVELY
//-----------------------------------------------------------

I'm not sure but it seems lto be a mix of stuff from the DLL behind the DLL and what you need to actually use "mycppdialdll.dll". If I understood you correctly, "mycppdialdll.dll" is supposed to be a simpler interface to the complicated original DLL? You don't need an interface class since there is no interface. You have a DLL with 4 functions. You're returning a void* from the function creating the NumberDialer in the original DLL and use that void* in the calls to your DLL. The object behind the void* is hidden in the DLL.

I'm sorry if I disturbed you but it seems in the beginning that you reply your coding
style are c++ builder expertise.

Not at all but thanks :-)

Br,
Ted
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 31, 2018 1:58 PM   in response to: Ted Lyngmo in response to: Ted Lyngmo
hi,

I will rework on the links you send,

and actually I was wrong in saying.....the Original DLL is not a DLL along...it's a .LIB or library...that also points a lib that calls the .DLL

anyway I'll message you back,,,,got to read first all your updated message.

thank you
roca robin

Posts: 140
Registered: 9/10/06
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 4, 2018 1:24 PM   in response to: roca robin in response to: roca robin
I think I got it now,
Alex helped me,
Ted helped me also...

But the solution I have is different.

thank you guys.

Got it this way,.....I really follow the Delphi style...

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <windows.h>
#include <system.hpp>

#pragma package(smart_init)
#pragma resource "*.dfm"

#pragma comment(lib,"mycppdialdll.lib")
#include "unumbercaller.cpp"

TForm1 *Form1;

//Edited:....
TNumberCaller *tcallerid;

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
//
//

//Corrected::::before does not creating anything...//////>>> It does create BUT empty....
FROM:
tcallerid = new TNumberCaller();
icallerid = (INumberCaller*)tcallerid->createNumberCaller(1,100.1);

Edited:....
//...So, I changed the code TO: like @Ted said..... now it creates TNumberCaller,Save and Load
tcallerid = new TNumberCaller();
tcallerid->createNumberCaller(1,100.1);
tcallerid->load(_x_filename_);
tcallerid->save(_y_filename_);

Edited:....
//... I also used this to import functions from external DLL, like @ Alex said,...//#include "unumbercaller.cpp"
//extern "C" __declspec(dllimport) TNumberCaller* __stdcall Create_NumberCaller( int dial1 = 1, double dial2 = dbldial );

//
//
}
john smith

Posts: 2
Registered: 2/14/18
Re: Importing a Routine Under a Different Name from a Dynamic Link Library  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 1:51 AM   in response to: roca robin in response to: roca robin
Big Update of RUSSIAN/USA/EU/WORLD dumps+pin. Valid rate 97-99%

- Selling mixed 1xx or 2xx codes;
- 100 tracks BULK 1xx cost $10,000; 1(1xx)=$500; 1(2xx)=$200;
- Replacing within 12 hours, invalid tracks only(videos+receipt mandatory);
- Accepting cashiers with $2500+two vouchers deposit from Mafiozosmafaz,irc,xxxxx
MIRC;

Feedbacks and reviews:http://australia101-201.boards.net

https://icq.com/chat/AoLC875WTg5cCxjRACE

https://www.youtube.com/watch?v=O9IWmf3qvo4

Best d+p updates and tools

Emv chipsotovX1 all in one software to write for Ommni3121, asr38, asr98 ETC FOR SALE

ATMCARD at jabber dot org

icq 611588027

Icq- 440588964

http://s15.zetaboards.com/club101201

Base Barflozm25. Was updated with 1.2k dumps ,200pcs T1T2T3+PIN .good approval Rate, No replace for this super

Base.!!

Track 1/2: %B5331572716170888^UNEMBOSSED/NAME^22091211160800000483000000?;5331572716170888=22091211160800000483?

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02