AG112297
asked on
Passing a string from a D3 exe to a BCB dll
I am trying to pass a string as an argument from a D3 exe to a BCB dll. The BCB docs indicate that if one uses a char pointer, it is not required to use bcbmm.dll. A doc at the Borland website, "Extending Delphi with DLLs" provides snippets illustrating how this is done. Unfortunately I can not get this to work.
BCB code:
extern "C" __pascal __declspec(dllexport) int AddVals(int nA, int nB, int nC, int nD)
{
return (nA+nB+nC+nD);
}
/*
This is from "Extending Delphi with DLLs" found at the Borland website
*/
int far _export pascal PassCharPtr(char far* strA)
{
MessageBox(NULL, strA, "GPC_TPL", MB_OK);
return (strlen(strA));
}
D3 code:
function ADDVALS(nA,nB,nC,nD: integer):integer; stdcall; far external 'GPC_TPL.DLL' index 2;
function PASSCHARPTR(strParam: PChar):integer; external 'GPC_TPL' index 1;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender : TObject);
const
StringLength = 255;
var
nRetVal: integer;
strA: array[0..StringLength] of char;
begin
nRetVal := ADDVALS(1,2,3,4);
ShowMessage(IntToStr(nRetV al));
StrPCopy(strA, 'Hello World!');
nRetVal := PASSCHARPTR(strA);
ShowMessage(IntToStr(nRetV al));
end;
The PassCharPtr method in the dll does not receive the string as a argument and returns the length of the string as 3 no matter what the string length really is.
BCB suggests adding bcbmm.lib to both the dll and exe. I cannot seem to add bcbmm.lib to the D3 exe.
When I add ShareMem.pas to the dll project and put ShareMem at the head of my uses list, I get the same results plus when I close the exe an InvalidPointer exception is thrown.
Suggestions on how to successfully pass a string (<255 char) as an argument from a D3 exe to a BCB dll method will be greatly appreciated.
thanks
A.G.
BCB code:
extern "C" __pascal __declspec(dllexport) int AddVals(int nA, int nB, int nC, int nD)
{
return (nA+nB+nC+nD);
}
/*
This is from "Extending Delphi with DLLs" found at the Borland website
*/
int far _export pascal PassCharPtr(char far* strA)
{
MessageBox(NULL, strA, "GPC_TPL", MB_OK);
return (strlen(strA));
}
D3 code:
function ADDVALS(nA,nB,nC,nD: integer):integer; stdcall; far external 'GPC_TPL.DLL' index 2;
function PASSCHARPTR(strParam: PChar):integer; external 'GPC_TPL' index 1;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender
const
StringLength = 255;
var
nRetVal: integer;
strA: array[0..StringLength] of char;
begin
nRetVal := ADDVALS(1,2,3,4);
ShowMessage(IntToStr(nRetV
StrPCopy(strA, 'Hello World!');
nRetVal := PASSCHARPTR(strA);
ShowMessage(IntToStr(nRetV
end;
The PassCharPtr method in the dll does not receive the string as a argument and returns the length of the string as 3 no matter what the string length really is.
BCB suggests adding bcbmm.lib to both the dll and exe. I cannot seem to add bcbmm.lib to the D3 exe.
When I add ShareMem.pas to the dll project and put ShareMem at the head of my uses list, I get the same results plus when I close the exe an InvalidPointer exception is thrown.
Suggestions on how to successfully pass a string (<255 char) as an argument from a D3 exe to a BCB dll method will be greatly appreciated.
thanks
A.G.
ASKER
Unfortunately Delphi 3 informs me that the ampersand is an "illegal character in input file" and as such will not compile. Thank you for the effort.
Ok, so i use C++ now...
try again with the "@" character.
// If that also does not compile, I will actually fire up
// delphi and re-invent the "address off" operator :-)
try again with the "@" character.
// If that also does not compile, I will actually fire up
// delphi and re-invent the "address off" operator :-)
ASKER
The D3 compiles but when it executes and invokes the dll's PassCharPtr method, the results are unchanged. I have been trying to find more information on the calling convention as I think that is where the problem might lie. FWIW both methods work fine when invoked from a BCB exe.
Thanks again.
Thanks again.
hmmm, I'll give this one last (this will be my last "answer") try:
Take another look at the Delphi declarations:
--
D3 code:
function ADDVALS(nA,nB,nC,nD: integer):integer; stdcall; far external 'GPC_TPL.DLL' index 2;
function PASSCHARPTR(strParam: PChar):integer; external 'GPC_TPL' index 1;
--
The second function, the one with the pchar, does NOT have a
"stdcall" keyword.
Happy new year. (even if this also does not help)
Take another look at the Delphi declarations:
--
D3 code:
function ADDVALS(nA,nB,nC,nD: integer):integer; stdcall; far external 'GPC_TPL.DLL' index 2;
function PASSCHARPTR(strParam: PChar):integer; external 'GPC_TPL' index 1;
--
The second function, the one with the pchar, does NOT have a
"stdcall" keyword.
Happy new year. (even if this also does not help)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I figured that out this afternoon. I next ran into a problem when I 'combined' the two methods into one, DoItAll(char*,int,int,int, int). Using the calling conventions above, the method wouldn't work. I finally tried the basic convention,
int __export DoItAll(LPTSTR strA, int nA, int nB, int nC, int nD)
and it worked. The name is mangled but since I will call the method ordinally from D3 it doesn't matter to me. Thanks for the help.
int __export DoItAll(LPTSTR strA, int nA, int nB, int nC, int nD)
and it worked. The name is mangled but since I will call the method ordinally from D3 it doesn't matter to me. Thanks for the help.
here.
Try this (and reject the answer if it does not work, I do not
remember exactly whenand why I had to pull this stunt)
replace:
nRetVal := PASSCHARPTR(strA);
with
nRetVal := PASSCHARPTR(&strA[0]);
and if it does work, well an "A" would be nice ;-)