Aboud Abdou
asked on
Communication between C++ program and Delphi DLL
Hello;
I have a c++ program which launch a Delphi DLL where there are informations i need in C++.
So I need to return data from Delphi to C++.
I make some tries, and the last succefull try was to pass a c++ pointer to function and use the function in the delphi side;
Until Now, everything is OK;
the problem occurs when i try to send string from Delphi to C++; I receive non comprehensible string; ( chinese letters + arabic letters + mathmatical symbols ).
after several tries; I noticed that in Delphi, the problem occurs if there is a UnicodeString or String in the program even if it is not in the string sent to C++.
If I have only PWideChar in the program, that works; if there is String or UnicodeString, AnsiString ..., (even if it is not concatenated to PWideChar), the received string is unreadable.
I hope find a solution for this problem. I will put some code in commentaires.
I have a c++ program which launch a Delphi DLL where there are informations i need in C++.
So I need to return data from Delphi to C++.
I make some tries, and the last succefull try was to pass a c++ pointer to function and use the function in the delphi side;
Until Now, everything is OK;
the problem occurs when i try to send string from Delphi to C++; I receive non comprehensible string; ( chinese letters + arabic letters + mathmatical symbols ).
after several tries; I noticed that in Delphi, the problem occurs if there is a UnicodeString or String in the program even if it is not in the string sent to C++.
If I have only PWideChar in the program, that works; if there is String or UnicodeString, AnsiString ..., (even if it is not concatenated to PWideChar), the received string is unreadable.
I hope find a solution for this problem. I will put some code in commentaires.
ASKER
Code Delphi which works
library DllDeTest;
uses
Winapi.Windows;
{$R *.res}
Const
MAX_LOOP = 100;
SLEEP_TIME = 100;
type
TFunc = procedure( infos: PWideChar);
procedure call( cppFunc : TFunc); stdcall;
var
I: Integer;
widechar: PWideChar;
begin
for I := 1 to MAX_LOOP do
begin
widechar := PWideChar('ABCD');
cppFunc( widechar );
sleep(SLEEP_TIME);
end;
end;
exports
call;
begin
end.
library DllDeTest;
uses
Winapi.Windows;
{$R *.res}
Const
MAX_LOOP = 100;
SLEEP_TIME = 100;
type
TFunc = procedure( infos: PWideChar);
procedure call( cppFunc : TFunc); stdcall;
var
I: Integer;
widechar: PWideChar;
begin
for I := 1 to MAX_LOOP do
begin
widechar := PWideChar('ABCD');
cppFunc( widechar );
sleep(SLEEP_TIME);
end;
end;
exports
call;
begin
end.
ASKER
Code Delphi which does not work
library DllDeTest;
uses
Winapi.Windows;
{$R *.res}
Const
MAX_LOOP = 100;
SLEEP_TIME = 100;
type
TFunc = procedure( infos: PWideChar);
procedure call( cppFunc : TFunc); stdcall;
var
I: Integer;
widechar: PWideChar;
str:String;
begin
for I := 1 to MAX_LOOP do
begin
str = IntToStr(I);
widechar := PWideChar(str);
cppFunc( widechar );
sleep(SLEEP_TIME);
end;
end;
exports
call;
begin
end.
library DllDeTest;
uses
Winapi.Windows;
{$R *.res}
Const
MAX_LOOP = 100;
SLEEP_TIME = 100;
type
TFunc = procedure( infos: PWideChar);
procedure call( cppFunc : TFunc); stdcall;
var
I: Integer;
widechar: PWideChar;
str:String;
begin
for I := 1 to MAX_LOOP do
begin
str = IntToStr(I);
widechar := PWideChar(str);
cppFunc( widechar );
sleep(SLEEP_TIME);
end;
end;
exports
call;
begin
end.
widechar := PWideChar(str);
this statement is wrong because str is an AnsiString and holds an array of ansi characters. if you cast this string to a PWideChar (pointer to wide characters), it is not a conversion but each pair of single-byte characters in the ansi string would be looked on as a wide character, what is not you wanted. moreover a wide char string must be terminated by a double-zero wide character what is only the case by accident if you run your code.
to come out of this you should use StringToWideChar function like that:
var
wideChars : array[0..11] of WideChar;
myString : String;
begin
// Set up our string
myString := 'Hello World';
// Copy to a WideChar format in our array
StringToWideChar(myString, wideChars, 12);
the wideChars array savely could be passed to the cpp callback function. be aware that your wide char array must be big enough to take the terminating double-zero char. it would be best to create a really big array which could take all possible return strings.
Sara
Hi Abdou,
What C++ compiler are you using? If it's Borland, things should work very cleanly as much of the C++ library, particularly the forms management, is written in Delphi.
What C++ compiler are you using? If it's Borland, things should work very cleanly as much of the C++ library, particularly the forms management, is written in Delphi.
ASKER
Hi Kent; No It is NOT Borland; It Is MSVC
ASKER
Hi Sara; Thanks a lot of your time; i will test this solution and i hope that will work;
I have a question related to your solution;
You fixed the length of the WideChar array to 12; what if i don't know previously the length of my string
thanks in advance
I have a question related to your solution;
You fixed the length of the WideChar array to 12; what if i don't know previously the length of my string
thanks in advance
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks Sara; Yes I already thought about the second solution but i find it not clean enough;
Your first solution look clean but I have always the probleme in the side of C++; I receive always non comprehensible string;
the signature of the function in C++ side is one of the two next signature:
void CallFunc(wchar_t* str);
void CallFunc(wchar_t wchars[]);
Any Hint!
Your first solution look clean but I have always the probleme in the side of C++; I receive always non comprehensible string;
the signature of the function in C++ side is one of the two next signature:
void CallFunc(wchar_t* str);
void CallFunc(wchar_t wchars[]);
Any Hint!
ASKER
The returned value in C++ Side
Err1.png
Err1.png
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you, for your help.
ASKER
#include <iostream>
#include <thread>
#include <string>
#include <windows.h>
//------------------------
using namespace std;
//------------------------
#define NombreDeMainLoop 100
#define SLEEP_TIME 100
//------------------------
void CallFunc(wchar_t* str)
{
wstring ws(str);
string st(ws.begin(), ws.end());
cout << "I have been called " << st << endl;
}
//------------------------
void __stdcall call()
{
HINSTANCE hDllDeTest = LoadLibrary(L"DllDeTest.dl
if (!hDllDeTest) {
std::cout << "could not load the dynamic library" << std::endl;
return;
}
typedef void(*Func) (wchar_t*);
typedef void (WINAPI* MyFunc)(Func);
MyFunc CallDelphi = (MyFunc)GetProcAddress(hDl
if (!CallFunc) {
std::cout << "could not locate the function" << std::endl;
return;
}
CallDelphi(&CallFunc);
}
//------------------------
int main()
{
thread T(call);
for (size_t i = 1; i <= NombreDeMainLoop; i++)
{
std::cout << ".........................
std::this_thread::sleep_fo
}
T.join();
}