Mac Office 2011 VBA and Dylib

后端 未结 1 1487
名媛妹妹
名媛妹妹 2021-01-25 02:45

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, ba

相关标签:
1条回答
  • 2021-01-25 03:02

    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
    
    0 讨论(0)
提交回复
热议问题