Link to home
Start Free TrialLog in
Avatar of Aboud Abdou
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.
Avatar of Aboud Abdou
Aboud Abdou

ASKER

Code C++
#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.dll");
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(hDllDeTest, "call");
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 << "......................................." << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME));
}
T.join();
}
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.
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.
Avatar of sarabande
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);

Open in new window


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.
Hi Kent; No It is NOT Borland; It Is MSVC
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
SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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!
The returned value in C++ Side
Err1.png
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you, for your help.