2012-03-23 80 views
1

我正在使用Mac OS中的Word 2011插件。目前,我需要在VBA宏中编写代码以从另一个应用程序(通过套接字通信)检索字符串。所以,基本上在Windows中,我可以简单地创建一个DLL,它可以帮助我与其他应用程序进行Socket通信,并将String值返回给VBA宏。Mac Office 2011 VBA和Dylib

但是,在Mac中,我可以构建.dylib(使用C语言)并使用VBA与dylib进行通信。但是,我在返回String时遇到了麻烦。我简单的C代码是一样的东西: 的char * tcpconnect(字符*参数) {}

首先,它总是包含CHR(0)字符。其次,我怀疑这个C函数将无法处理Unicode字符串。

你们有没有经验或有类似的例子?

感谢,

大卫

+0

我认为我很清楚:VBA - > .dylib - >套接字通信。 – mashix 2012-03-23 06:34:42

回答

1

我原来的职位是使用malloc()模仿SysAllocStringByteLen()的尝试,但是当Excel尝试释放返回的内存,这将失败。使用Excel来分配存储器修复问题,并且是较少的代码,以及,例如:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#define LPCSTR const char * 
#define LPSTR char * 
#define __declspec(dllexport) 
#define WINAPI 

char *saved_string = NULL; 
int32_t saved_len = -1; 

#define _CLEANUP if(saved_string) free(saved_string) 

__attribute__((destructor)) 
static void finalizer(void) { 
    _CLEANUP; 
} 

int32_t __declspec(dllexport) WINAPI get_saved_string(LPSTR pszString, int cSize) { 
    int32_t old_saved_len = saved_len; 
    if(saved_len > 0 && cSize >= saved_len) 
    strncpy(pszString, saved_string, saved_len); 
    if(saved_string) { 
    free(saved_string); 
    saved_string = NULL; 
    saved_len = -1; 
    } 
    return old_saved_len; 
} 

int32_t __declspec(dllexport) WINAPI myfunc(LPCSTR *pszString) { 
    int len = (pszString && *pszString ? strlen(*pszString) : 0); 
    saved_string = malloc(len + 5); 
    saved_len = len + 5; 
    sprintf(saved_string, "%s%.*s", "abc:", len, *pszString); 
    return saved_len; 
} 

编译上面

gcc -g -arch i386 -shared -o test.dylib test.c 

然后,在:

在test.c的

新的VBA模块,使用下面的并运行“测试”,这将在前面加上“ABC”字符串“您好”,并把结果输出的调试窗口:

Public Declare Function myfunc Lib "<colon-separated-path>:test.dylib" (s As String) As Long 
Public Declare Function get_saved_string Lib "<colon-separated-path>:test.dylib" (ByVal s As String, ByVal csize As Long) As Long 

Option Explicit 

Public Function getDLLString(string_size As Long) As String 
    Dim s As String 
    If string_size > 0 Then 
     s = Space$(string_size + 1) 
     get_saved_string s, string_size + 1 
    End If 
    getDLLString = s 
End Function 

Public Sub test() 
Debug.Print getDLLString(myfunc("hi there")) 
End Sub 
+0

仍然不知道为什么这是downvoted,但会对任何改进想法感兴趣 – mwag 2015-03-13 21:07:54