How do I return a string from DLL to Inno Setup Pascal Script - dll

I have two C functions in a DLL which are defined in the definition file and are exported for using in Inno Setup.
char* __stdcall GetName()
{
return "Kishore";
}
void __stdcall getName(char* strName)
{
strcpy(strName, "Kishore");
}
The Inno Setup code will load the custom DLL and call the function/procedure to return the names
{ Inno Setup script }
[Code]
procedure getName(MacAddress: String);
external 'getName#files:MyDll.dll stdcall setuponly';
function GetName():PAnsiChar;
external 'GetName#files:MyDll.dll stdcall setuponly';
function NextButtonClick(CurPage: Integer): Boolean;
var
StrName: String;
begin
SetLength(StrName,15);
getName(StrName); { displaying only single character }
StrName := GetName(); { this call is crashing }
end
How can I retrieve the name in Inno Setup script without it crashing?

GetName should return a const char *, however it is otherwise fine as written. Note however that returning a string like this can only ever possibly work for literal string constants, as shown above. You cannot use this pattern to return a calculated string value (if you try that, it will likely crash or give corrupted data); thus getName is wrong.
Also note that while C is case sensitive, Pascal is not, so getName and GetName are the same function in the Inno script. You might be getting away with this in the above case because the parameters are different, but I wouldn't rely on that -- you should give them distinct names. (Don't use the same name on the C side either, as DLL exports are sometimes looked up case-insensitively too.)
To return a calculated string, you should use a pattern like this:
DLL code:
void __stdcall CalculateName(char *buffer, size_t size)
{
strncpy(buffer, "whatever", size);
buffer[size-1] = 0;
}
Inno code:
procedure CalculateName(Buffer: AnsiString; Max: Cardinal);
external 'CalculateName#files:my.dll stdcall';
...
Max := 16;
Buffer := StringOfChar(#0, Max);
CalculateName(Buffer, Max);
SetLength(Buffer, Pos(#0, Buffer) - 1);
...
A few acceptable variations exist, for example you can make the DLL function return the number of characters actually written to the buffer, and use that in the subsequent SetLength rather than calling Pos to find the null terminator.
But you must:
Ensure that both sides are using the same string types, either both ANSI or both Unicode.
ANSI Inno Setup supports only ANSI strings with its String type.
Unicode Inno Setup supports either ANSI strings with AnsiString or Unicode strings with String.
When using Unicode strings, ensure that both sides agree whether Max and/or the return value is specified in characters or bytes (the example code assumes it's in characters).
Prior to calling the function, use either SetLength or StringOfChar to ensure that the buffer has been sized to the required maximum possible result length.
Ensure the called function does not try to write past this maximum length (which is easier if this is provided as a parameter to the function).
Ensure that if you're using Pos, the called function must ensure the value is null-terminated (or you need to be more careful than shown in the example).
Ensure that after the call you truncate the string to the actual length, either by using a returned value or by finding the null terminator.
One of the constraints in play here is that memory allocated by one side must be freed by the same side. You cannot safely release memory allocated on the "wrong" side of the DLL boundary, in either direction.

Related

In Hive, what does the 'positive' function do?

I'm working on an item-based recommender using data stored in Hive tables and stumbled across a similar scenario in Sagar Prasad's blog. I notice that he uses the POSITIVE function on the hashes of the user/product.
I'm a bit confused as to why this function exists. The documentation states that this function takes an int or double and returns that value:
"positive(INT/DOUBLE a) returns a"
For example:
hive> select positive(-1);
-1
Does that mean that the function doesn't do anything? Or am I missing some subtle nuance?
Under the hood this function is GenericUDFOPPositive.java which extends GenericUDFBaseUnary.java. positive can also be called simply as +.
For numeric types, this function does indeed do effectively nothing. For text types, it appears to attempt to do a conversion to double, since GenericUDFBaseUnary.java contains the following:
private PrimitiveTypeInfo deriveResultTypeInfo(PrimitiveTypeInfo typeInfo) {
switch(typeInfo.getPrimitiveCategory()) {
case STRING:
case VARCHAR:
case CHAR:
return TypeInfoFactory.doubleTypeInfo;
default:
return typeInfo;
}
}
However this doesn't seem to actually work, as calling positive on a string simply returns the string. This implies that at the least, the type signature of this function in the documentation is wrong, as it accepts more than just double and int.
Don't worry about being confused, having read the source code to try and work out what this function is for, I'm also now confused about why it exists!
https://github.com/apache/hive/blob/release-0.14.0/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFOPPositive.java
https://github.com/apache/hive/blob/release-0.14.0/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFBaseUnary.java

Why does Go allow compilation of unused function parameters?

One of the more notable aspects of Go when coming from C is that the compiler will not build your program if there is an unused variable declared inside of it. So why, then, is this program building if there is an unused parameter declared in a function?
func main() {
print(computron(3, -3));
}
func computron(param_a int, param_b int) int {
return 3 * param_a;
}
There's no official reason, but the reason given on golang-nuts is:
Unused variables are always a programming error, whereas it is common
to write a function that doesn't use all of its arguments.
One could leave those arguments unnamed (using _), but then that might
confuse with functions like
func foo(_ string, _ int) // what's this supposed to do?
The names, even if they're unused, provide important documentation.
Andrew
https://groups.google.com/forum/#!topic/golang-nuts/q09H61oxwWw
Sometimes having unused parameters is important for satisfying interfaces, one example might be a function that operates on a weighted graph. If you want to implement a graph with a uniform cost across all edges, it's useless to consider the nodes:
func (graph *MyGraph) Distance(node1,node2 Node) int {
return 1
}
As that thread notes, there is a valid argument to only allow parameters named as _ if they're unused (e.g. Distance(_,_ Node)), but at this point it's too late due to the Go 1 future-compatibility guarantee. As also mentioned, a possible objection to that anyway is that parameters, even if unused, can implicitly provide documentation.
In short: there's no concrete, specific answer, other than that they simply made an ultimately arbitrary (but still educated) determination that unused parameters are more important and useful than unused local variables and imports. If there was once a strong design reason, it's not documented anywhere.
The main reason is to be able to implement interfaces that dictate specific methods with specific parameters, even if you don't use all of them in your implementation. This is detailed in #Jsor's answer.
Another good reason is that unused (local) variables are often the result of a bug or the use of a language feature (e.g. use of short variable declaration := in a block, unintentionally shadowing an "outer" variable) while unused function parameters never (or very rarely) are the result of a bug.
Another reason can be to provide forward compatibility. If you release a library, you can't change or extend the parameter list without breaking backward compatibility (and in Go there is no function overloading: if you want 2 variants with different parameters, their names must be different too).
You may provide an exported function or method and add extra - not yet used - or optional parameters (e.g. hints) to it in the spirit that you may use them in a future version / release of your library.
Doing so early will give you the benefit that others using your library won't have to change anything in their code.
Let's see an example:
You want to create a formatting function:
// FormatSize formats the specified size (bytes) to a string.
func FormatSize(size int) string {
return fmt.Sprintf("%d bytes", size)
}
You may as well add an extra parameter right away:
// FormatSize formats the specified size (bytes) to a string.
// flags can be used to alter the output format. Not yet used.
func FormatSize(size int, flags int) string {
return fmt.Sprintf("%d bytes", size)
}
Then later you may improve your library and your FormatSize() function to support the following formatting flags:
const (
FlagAutoUnit = 1 << iota // Automatically format as KB, MB, GB etc.
FlagSI // Use SI conversion (1000 instead of 1024)
FlagGroupDecimals // Format number using decimal grouping
)
// FormatSize formats the specified size (bytes) to a string.
// flags can be used to alter the output format.
func FormatSize(size int, flags int) string {
var s string
// Check flags and format accordingly
// ...
return s
}

DllImport and return parameters

I am working on hardware testing. Our test framework is written in C# but we are using native dlls to talk to hardware.
Say we have a C++ method:
unsigned char someMethod(unsigned long * nativeStatus)
which in turns executes an embedded command and returns a status when command completes.
To use it we create a wrapper
[DllImport(#"native.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
internal static extern Byte someMethod(ref UInt32 managedStatus)
This works fine. But there is a scenario when someMethod call does not actually execute a command but just adds it to a sequence. Then the sequence can be executed by sending a special command say ExecuteSequence. As the sequence is being executed C++ code updates the nativeStatus by just copying the data into the memory referenced by the nativeStatus pointer. As the sequence completes ExecuteSequence method returns. At this time I am sure that all data (nativeStatus in this case) is updated. Will my managedStatus be correctly updated as well? I heard that in this case managedStatus and nativeStatus are not pointing to the same memory. Marshaler just returns a copy of nativeState after call completes. If not what is the solution? Do I need to use the unsave keyword and put my code creating and executing a sequence in the fixed{} block?
[DllImport(#"native.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
internal static unsave extern Byte someMethod(UInt32 * managedStatus)
So what you need is a variable location of which will not change over a timespan.
Yes, you can use fixed{} for that.
Alternatively, you can pin that variable:
private uint g_Pinnable = 0;
...
var gc = System.Runtime.InteropServices.GCHandle.Alloc(g_Pinnable, System.Runtime.InteropServices.GCHandleType.Pinned);
try
{
// Pass 'ref g_Pinnable' to API
// Then execute the sequence.
}
finally
{
gc.Free(); // Reference to g_Pinnable may be invalid after this point
}

Ignore Ada Function Return Values

Is there a way to ignore return values in Ada functions?
I have a function which imports from an Intrinsic.
subtype int32 is Interfaces.Interger_32;
function Intrinsic_Sync_Add_And_Fetch
(P : access int32; I : int32) return int32;
pragma Import(
Intrinsic,
Intrinsic_Sync_Add_And_Fetch,
"__sync_add_and_fetch_4");
If I want to use this in a procedure, I need to accept the return value or I will get a compiler error:
cannot use function Intrinsic_Sync_Add_And_Fetch in procedure call.
But, if I create a variable that simply takes the return value of the function and is never used then I get compiler warnings. Obviously, I'd rather avoid those.
I can't very well assign the value back to the value I'm adding to; this would undermine the point of the add operation being atomic.
There is the option of taking the value and doing something with it, like:
val := Intrinsic_Sync_Add_And_Fetch(...);
if val := 0 then null; end if;
It forces the code to compile without errors or warnings, but it seems stupid to me. How can I "get around" this language feature and safely ignore the return value?
Edit: What is __sync_add_and_fetch_4?
This is a built-in atomic operation available on Intel CPUs. As such, part of my Autoconf/Automake process would be deciding if the operation is available, and use a fallback implementation, which involves a critical section, if it's not.
You can read about this and similar operations in GCC's section on atomic builtins.
The __sync_add_and_fetch_4 does pretty much exactly what it says. In C, it would look something like this:
int32_t __sync_add_and_fetch_4(int32_t *ptr, int32_t value) {
*ptr += value;
return *ptr;
}
So it's an atomic addition operation, which returns the result of the addition. Basically, it's an atomic += operator. The _4 means that it takes a 4-byte integer.
Edit: I understand that I could probably just switch off that particular compiler warning, but that always feels dirty to me. If there's a solution available that allows me to continue using -Wall -Werror then I'd love to see it.
declare
dummy : constant return_type := my_function;
pragma Unreferenced (dummy);
begin null; end;
or write a wrapper procedure.
If you never want to reference the return value, why not declare the subprogram as a procedure? The value is going to be returned in a register, so throwing it away won’t cause a lot of grief. (I stand to be corrected on this one!)
subtype int32 is Interfaces.Integer_32;
procedure Intrinsic_Sync_Add_And_Fetch
(P : access int32; I : int32);
pragma Import(
Intrinsic,
Intrinsic_Sync_Add_And_Fetch,
"__sync_add_and_fetch_4");
You said you're only targeting the GNAT compiler. The GNAT User's Guide says:
Note that a special exemption applies to variables which contain any of the substrings DISCARD, DUMMY, IGNORE, JUNK, UNUSED, in any casing. Such variables are considered likely to be intentionally used in a situation where otherwise a warning would be given, so warnings of this kind are always suppressed for such variables.
So the simplest solution to your problem is :
unused := Intrinsic_Sync_Add_And_Fetch(...);
Though you might want to wrap that in a procedure if you are going to use it more than a couple of times :
procedure Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32) is
unused : int32;
begin
unused := Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32);
end Intrinsic_Sync_Add_And_Fetch;
i don't know of any way to ignore the return value of a function in Ada: the language has been especially designed to force you to store those return values.
personally, i would store the return value and ignore any warning regarding the use of the variable. anyway, the said warning is quite strange since the variable is indeed used to store the return value.

P/Invoke with [Out] StringBuilder / LPTSTR and multibyte chars: Garbled text?

I'm trying to use P/Invoke to fetch a string (among other things) from an unmanaged DLL, but the string comes out garbled, no matter what I try.
I'm not a native Windows coder, so I'm unsure about the character encoding bits. The DLL is set to use "Multi-Byte Character Set", which I can't change (because that would break other projects). I'm trying to add a wrapper function to extract some data from some existing classes. The string in question currently exists as a CString, and I'm trying to copy it to an LPTSTR, hoping to get it into a managed StringBuilder.
This is what I have done that I believe is the closest to being correct (I have removed the irrelevant bits, obviously):
// unmanaged function
DLLEXPORT void Test(LPTSTR result)
{
// eval->result is a CString
_tcscpy(result, (LPCTSTR)eval->result);
}
// in managed code
[DllImport("Test.dll", CharSet = CharSet.Auto)]
static extern void Test([Out] StringBuilder result);
// using it in managed code
StringBuilder result = new StringBuilder();
Test(result);
// contents in result garbled at this point
// just for comparison, this unmanaged consumer of the same function works
LPTSTR result = new TCHAR[100];
Test(result);
Really appreciate any tips! Thanks!!!
One problem is using CharSet.Auto.
On an NT-based system this will assume that the result parameter in the native DLL will be using Unicode. Change that to CharSet.Ansi and see if you get better results.
You also need to size the buffer of the StringBuilder that you're passing in:
StringBuilder result = new StringBuilder(100); // problem if more than 100 characters are returned
Also - the native C code is using 'TCHAR' types and macros - this means that it could be built for Unicode. If this might happen it complicates the CharSet situation in the DllImportAtribute somewhat - especially if you don't use the TestA()/TestW() naming convention for the native export.
Dont use out paramaeter as you are not allocating in c function
[DllImport("Test.dll", CharSet = CharSet.Auto)]
static extern void Test(StringBuilder result);
StringBuilder result = new StringBuilder(100);
Test(result);
This should work for you
You didn't describe what your garbled string looks like. I suspect you are mixing up some MBCS strings and UCS-2 strings (using 2-byte wchar_ts). If every other byte is 0, then you are looking a UCS-2 string (and possibly misusing it as an MBCS string). If every other byte is not 0, then you are probably looking at an MBCS string (and possibly misusing it as a Unicode string).
In general, I would recommend not using TCHARs (or LPTSRs). They use macro magic to switch between char (1 byte) and wchar_t (2 bytes), depending on whether _UNICODE is #defined. I prefer to explicit use chat and wchar_t to make the codes intent very clear. However, you will need to call the -A or -W forms of any Win32 APIs that use TCHAR parameters: e.g. MessageBoxA() or MessageBoxW() instead of MessageBox() (which is a macro that checks whether _UNICODE is #defined.
Then you should change CharSet = CharSet.Auto to something CharSet = CharSet.Ansi (if both caller and callee are using MBCS) or CharSet = CharSet.Unicode (if both caller and callee are using UCS-2 Unicode). But it sounds like your DLL is using MBCS, not Unicode.
pinvoke.net is a great wiki reference with many examples of P/Invoke function signatures for Win32 APIs: