Mac Office 2011 VBA and Dylib

2019-03-02 13:28发布

问题:

I'm working on a Word 2011 plugin in Mac OS. Currently, I need to write a code in VBA Macro to retrieve a String from another application (through Socket communication). So, basically in Windows, I can simply make a DLL which help me to do Socket communication with the other application and return the String value to VBA Macro.

However, in Mac, I'm able to build a .dylib (in C) and using VBA to communicate with the dylib. However, I'm having a trouble with the return String. My simple C code is something like: char * tcpconnect(char* arguments) {}

First, it always contains Chr(0) characters. Secondly, I suspected that this C function will not be able to handle Unicode String.

Do you guys have any experiences or have any similar example of this?

Thanks,

David

回答1:

My original post was an attempt to imitate SysAllocStringByteLen() using malloc(), but this will fail when Excel tries to free the returned memory. Using Excel to allocate the memory fixes that issue, and is less code as well, e.g.:

in 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;
}

Compile the above with

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

Then, in a new VBA module, use the below and run "test", which will prepend "abc:" to the string "hi there" and output the result the debug window:

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