I’m currently writing a C dynamic library in MacOSX, the functions are then used in Excel (2011) using the VBA, e.g.:
Declare Function TestF Lib "path_to_lib:mylib.dylib" Alias "test" (ByRef res As String) As String
This works fine for functions that return integers etc., but I can’t figure out how to pass strings back to VBA. My C function looks like this:
char* test(char *res)
{
res = "test";
return res;
}
but calling the function TestF in VBA as
Dim res As String
res = TestF(res)
crashes Excel…
If I use a function that is provided by the MathLink (Mathematica) library, e.g.
#include "mathlink.h"
char* test(MLINK link, char *res)
{
MLGetString(link, &res);
return res;
}
this function successfully assigns a string to “res” that I can use in VBA. The information on MLGetString can be found here: http://reference.wolfram.com/mathematica/ref/c/MLGetString.html.
So apparently, this function is able to create a string and pass it to res and I can use the string in VBA then. So any ideas how this function does that, or how I could pass a string to VBA without having to use OLE etc.?
Strings in Visual Basic are represented using
BSTRobjects: they consist of a pointer to a null-terminated wide-character string (UTF-16) which is preceded by a 4-byte length prefix. For example, here’s what the 4-character string “test” looks like in memory on a little-endian machine:Most importantly, the
BSTRpointer itself points to the start of the string (the first74byte in this example), not the length prefix.For reading
BSTRs, you can just treat them as regular pointers to wide-character strings, and you’ll be all right for the most part. But if you need to write/create them, it’s a little trickier.When creating
BSTRs, you normally allocate them usingSysAllocString(and its relatives) and deallocate them usingSysFreeString. You need to figure out how Excel on OS X exposes those functions (likely through the OLE dynamic library), since they’re not standard C. If you try to return a string that wasn’t allocated throughSysAllocString, then Excel is going to try to free it usingSysFreeString, which will likely corrupt your heap and crash your program. So don’t do that.Also note that by default, a
wchar_thas a size of 4 bytes, not 2, on OS X, so you can’t use thewchar_tdata type when dealing withBSTRs—you need to use an explicit 16-bit data type (such asuint16_t), or compile with the-fshort-wcharcompiler option to forcewchar_tto be 2 bytes, but be aware of the binary incompatibility issues that that may cause.