I have a C# DLL which exposes a function using Unmanaged Exports which is called directly by an Inno Setup Pascal script. This function needs to return a string to Inno Setup. My question is how can I accomplish this?
My preferred method is to pass a buffer from Inno Setup to the C# function which will return the string inside this buffer. I've come up with this code:
C# function:
[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
static int Test([Out, MarshalAs(UnmanagedType.LPWStr)] out string strout)
{
strout = "teststr";
return strout.Length;
}
Inno Setup script:
function Test(var res: String):Integer; external 'Test@files:testdll.dll stdcall';
procedure test1;
var
Res: String;
l: Integer;
begin
SetLength(Res,256);
l := Test(Res);
{ Uncommenting the following line causes an exception }
{ SetLength(Res,l); }
Log('"Res"');
end;
When I run this code the Res
variable is empty (I see "" in the log)
How can I return a string from this DLL?
Note that I am using the Unicode version of Inno Setup. I also don't want to use COM to call this function nor to allocate a buffer in the DLL and return it to Inno Setup.
using printf() If we want to do a string output in C stored in memory and we want to output it as it is, then we can use the printf() function. This function, like scanf() uses the access specifier %s to output strings. The complete syntax for this method is: printf("%s", char *s);
c=a+b; return c; We can replace with single-step like return a+b; If you forget to return a value in a function, it returns the warning message in most of the C compilers.
I would suggest you to use the BSTR
type, which is used to be a data type for interop function calls. On your C# side you'd marshall your string as the UnmanagedType.BStr
type and on the Inno Setup side you'd use the WideString
, which is compatible with the BSTR
type. So your code would then change to this (see also the Marshalling sample
chapter of the Unmanaged Exports docs):
[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
static int Test([MarshalAs(UnmanagedType.BStr)] out string strout)
{
strout = "teststr";
return 0; // indicates success
}
And on the Inno Setup side with the use of WideString
to this:
[Code]
function Test(out strout: WideString): Integer;
external 'Test@files:testdll.dll stdcall';
procedure CallTest;
var
retval: Integer;
str: WideString;
begin
retval := Test(str);
{ test retval for success }
Log(str);
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With