在MacOSX中将字符串返回到VBA [英] Return string to VBA in MacOSX

查看:102
本文介绍了在MacOSX中将字符串返回到VBA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在MacOSX中编写C动态库,然后使用VBA在Excel(2011)中使用这些函数,例如:

Declare Function TestF Lib "path_to_lib:mylib.dylib" Alias "test" (ByRef res As String) As String

这对于返回整数等的函数很好用,但是我不知道如何将字符串传递回VBA.我的C函数如下所示:

char* test(char *res)
{
  res = "test";
  return res;
}

但在VBA中将函数TestF调用为

Dim res As String
res = TestF(res)

崩溃Excel ... 如果我使用MathLink(Mathematica)库提供的功能,例如

#include "mathlink.h"
char* test(MLINK link, char *res)
{
  MLGetString(link, &res);
  return res;
}

此函数成功将字符串分配给我可以在VBA中使用的"res".可以在以下位置找到有关MLGetString的信息: http://reference.wolfram.com/mathematica/ref/c/MLGetString.html .

因此,显然,此函数能够创建一个字符串并将其传递给res,然后我可以在VBA中使用该字符串.那么,关于此函数如何实现的任何想法,或者我如何可以在不使用OLE等的情况下将字符串传递给VBA?

解决方案

字符串Visual Basic 使用BSTR对象表示:它们由指向以空字符结尾的宽字符字符串(UTF-16)的指针组成,该字符串以4字节长的前缀开头 .例如,这是一个4位字符的字符串"test"在小字节序机器上的内存中的样子:

+-------------+-------+-------+-------+-------+-------+
| 08 00 00 00 | 74 00 | 65 00 | 73 00 | 74 00 | 00 00 |
+-------------+-------+-------+-------+-------+-------+
 Length:        't'     'e'     's'     't'     '\0'
 8 bytes
 (not including null)

最重要的是,BSTR指针本身指向字符串的开头(在此示例中为第一个74字节),不是长度前缀.

对于阅读BSTR,您可以将它们视为指向宽字符字符串的常规指针,并且在大多数情况下都可以.但是,如果您需要编写/创建它们,那会有些棘手.

创建BSTR时,通常使用 SysFreeString .您需要弄清楚OS X上的Excel如何公开这些功能(可能通过OLE动态库),因为它们不是标准的C.如果尝试返回未通过SysAllocString分配的字符串,则Excel是将尝试使用SysFreeString释放它,这很可能会破坏您的堆并使程序崩溃.所以不要那样.

还要注意,默认情况下,wchar_t的大小为4字节,而不是2,在OS X上为2,因此在处理BSTR时不能使用wchar_t数据类型-您需要使用显式的16位数据类型(例如uint16_t),或使用-fshort-wchar编译器选项进行编译,以强制wchar_t为2字节,但要注意可能引起的二进制不兼容问题.

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 BSTR objects: 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:

+-------------+-------+-------+-------+-------+-------+
| 08 00 00 00 | 74 00 | 65 00 | 73 00 | 74 00 | 00 00 |
+-------------+-------+-------+-------+-------+-------+
 Length:        't'     'e'     's'     't'     '\0'
 8 bytes
 (not including null)

Most importantly, the BSTR pointer itself points to the start of the string (the first 74 byte 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 using SysAllocString (and its relatives) and deallocate them using SysFreeString. 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 through SysAllocString, then Excel is going to try to free it using SysFreeString, which will likely corrupt your heap and crash your program. So don't do that.

Also note that by default, a wchar_t has a size of 4 bytes, not 2, on OS X, so you can't use the wchar_t data type when dealing with BSTRs—you need to use an explicit 16-bit data type (such as uint16_t), or compile with the -fshort-wchar compiler option to force wchar_t to be 2 bytes, but be aware of the binary incompatibility issues that that may cause.

这篇关于在MacOSX中将字符串返回到VBA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆