cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
ISViper
Level 3

Failed to call a function inside a Delphi DLL

Hello everybody, first post ever, please help help, I need it urgent pls!

I have a DLL (MyDLL.dll) written in Delphi with the signature is

procedure MyFunction(const Str: PChar; var ReturnValue: PChar); export; stdcall;
The first argument is a string, that string will be proceeded and returned as the 2nd argument.

In InstallScript, no matter what I did, I still couldn't retrieve the correct value of the 2nd parameter. If I attach the DLL and debug in a sample application written in Delphi, the value returns correctly all the time.

Here are my sample snippets in InstallScript:
Case 1:

Define:
prototype MyDLL.MyFunction(STRING, POINTER);

Call:
STRING szTemp1, szTemp2;
szTemp1 = "test";
MyDLL.MyFunction(szTemp1, &szTemp2);
MessageBox("szTemp2 is returned = " + szTemp2, WARNING);

Result:
szTemp2 always returns nothing. In my expectation, szTemp2 should return "test1"


Case 2:

Define:
prototype MyDLL.MyFunction(STRING, BYREF STRING);

Call:

STRING szTemp1, szTemp2;
szTemp1 = "test";
MyDLL.MyFunction(szTemp1, szTemp2);
MessageBox("szTemp2 is returned = " + szTemp2, WARNING);

Result:
szTemp2 always returns nothing. In my expectation, szTemp2 should return "test1"



If you see anything wrong, please kindly help. I really appreciate your time and advice! Thank you very much.
Labels (1)
0 Kudos
(4) Replies
ISViper
Level 3

Just one more description in case you question, I already Load the DLL and from my logs, I know for sure the DLL function was entered.

I also tried this
prototype MyDLL.MyFunction(BYREF STRING, BYREF STRING);

or
prototype MyDLL.MyFunction(BYVAL STRING, BYREF STRING);

didn't work either 😞
0 Kudos
RobertDickau
Flexera Alumni

Your second prototype (BYVAL STRING, BYREF STRING) looks right. Can you display the input parameter (first parameter) inside the DLL function in a message box to see if the value is coming through?

Also, what version of Delphi are you using? It sounds as if recent versions use wide characters, so you might want to use (BYVAL WSTRING, BYREF WSTRING) in the prototype, and WSTRING for the variables.
0 Kudos
ISViper
Level 3

Thanks for the reply Robert.

I created log inside the dll, therefore, I could see the value transferred correctly from InstallScript to Dll (the first BYVAL parameter).

I'm using Delphi 6 + InstallShield 2012 Spring. Actually, from the project history, I saw that my function used to work at some points in the past with InstallShield 6 (of course the person worked on the installer at that moment is no longer working with us now). It stopped working around InstallShield 2009 and higher, I guess.

After one day researching around, I found this one http://community.flexerasoftware.com/showthread.php?199512-Problem-using-ANSI-tring-for-folder-path-in-Installshield-2011. I have exactly the same issue as that post. But when I tried to use WSTRING (as you also mentioned), the return value to InstallScript is still garbage. The log inside my dll shows that the value was correct before returning it to InstallScript.

Since the post also mentioned that the issue was solved after he converted his delphi code to fully support Unicode, I also tried myself. The thing is I'm not that good at Delphi (or you can say I know nothing about Delphi), I have no idea if my conversion was correct or not. After converting my delphi DLL (the compiler didn't complain me), tried it, InstallScript still received garbage returned value.

I really have no idea where to go now since I tried whatever I could. I shall talk to my delphi developer when he's back after the vacation too. I really hope to find someone encountering the same issue so that I can take some advice. Please kindly advise if you have any idea around this issue.
0 Kudos
ISViper
Level 3

I found the solution for myself. Just leave here some lines in case someone hits the same issue later.
For my case, I didn't have to convert my delphi dll to support Unicode.
What I did inside the dll function was that using a temporary string to receive whatever value I want to return. Don't use directly PChar. After that, I use StrCopy to copy the value from that string to my PChar variable. Remove var in front of the returned value in the function prototype.

It looks like this:

procedure MyFunction(const Str: PChar; ReturnValue: PChar); export; stdcall;
var
strTemp: string;
begin

strTemp = something;
StrCopy(ReturnValue, Pchar(strTemp));

end;
exports MyFunction;
0 Kudos