【问题标题】:Mac Office 2011 VBA and DylibMac Office 2011 VBA 和 Dylib
【发布时间】:2012-03-23 03:28:33
【问题描述】:

我正在开发 Mac OS 中的 Word 2011 插件。目前,我需要在 VBA 宏中编写代码以从另一个应用程序(通过 Socket 通信)检索字符串。因此,基本上在 Windows 中,我可以简单地制作一个 DLL,帮助我与其他应用程序进行 Socket 通信并将字符串值返回给 VBA 宏。

但是,在 Mac 中,我能够构建一个 .dylib(在 C 中)并使用 VBA 与 dylib 进行通信。但是,我遇到了返回字符串的问题。我的简单 C 代码类似于: char * tcpconnect(char* 参数) {}

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

你们有什么经验或者有类似的例子吗?

谢谢,

大卫

【问题讨论】:

  • 我想我说得很清楚了:VBA -> .dylib -> Socket 通信。

标签: string macos vba dylib


【解决方案1】:

我最初的帖子是尝试使用 malloc() 来模仿 SysAllocStringByteLen(),但是当 Excel 尝试释放返回的内存时,这将失败。使用 Excel 分配内存可以解决该问题,并且代码也更少,例如:

在 test.c 中:

#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

然后,在一个新的 VBA 模块中,使用下面的代码并运行“test”,它将在字符串“hi there”前面加上“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

【讨论】:

  • 仍然不知道为什么这被否决,但会对任何改进想法感兴趣
猜你喜欢
  • 1970-01-01
  • 2011-09-02
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多