Passing strings from VBA to C++ DLL

后端 未结 5 717
太阳男子
太阳男子 2021-02-05 11:31

I\'m really confused about passing strings from VBA to C++. Here\'s the VBA code:

Private Declare Sub passBSTRVal Lib \"         


        
5条回答
  •  长发绾君心
    2021-02-05 11:52

    Ok, so I know I set bounty to draw out a fuller response on the IDL idea but I have had a go at this myself. So I opened a ATL project, changed the idl to the following

    // IDLForModules.idl : IDL source for IDLForModules
    //
    
    // This file will be processed by the MIDL tool to
    // produce the type library (IDLForModules.tlb) and marshalling code.
    
    import "oaidl.idl";
    import "ocidl.idl";
    
    [
        helpstring("Idl For Modules"),
        uuid(EA8C8803-2E90-45B1-8B87-2674A9E41DF1),
        version(1.0),
    ]
    library IDLForModulesLib
    {
        importlib("stdole2.tlb");
    
        [
            /* dllname attribute https://msdn.microsoft.com/en-us/library/windows/desktop/aa367099(v=vs.85).aspx */
            dllname("IdlForModules.dll"),
            uuid(4C1884B3-9C24-4B4E-BDF8-C6B2E0D8B695)
        ]
        module Math{
            /* entry attribute https://msdn.microsoft.com/en-us/library/windows/desktop/aa366815(v=vs.85).aspx */
            [entry(656)] /* map function by entry point ordinal */
            Long _stdcall Abs([in] Long Number);
        }
        module Strings{
            [entry("pUpper")] /* map function by entry point name */
            BSTR _stdcall Upper([in] BSTR Number);
        }
    };
    

    Then in the main cpp file I added

    #include 
    #include 
    
    INT32 __stdcall _MyAbs(INT32 Number) {
        return abs(Number);
    }
    
    BSTR __stdcall pUpper(BSTR sBstr)
    {
        // Get the BSTR into the wonderful world of std::wstrings immediately
        std::wstring sStd(sBstr);
    
        // Do some "Mordern C++" iterator style op on the string
        std::transform(sStd.begin(), sStd.end(), sStd.begin(), ::toupper);
    
        // Dig out the char* and pass to create a return BSTR
        return SysAllocString(sStd.c_str());
    }
    

    And in the DEF file I edited it to be

    ; MidlForModules.def : Declares the module parameters.
    
    LIBRARY
    
    EXPORTS
        DllCanUnloadNow     PRIVATE
        DllGetClassObject   PRIVATE
        DllRegisterServer   PRIVATE
        DllUnregisterServer PRIVATE
        DllInstall      PRIVATE
        _MyAbs @656
        pUpper
    

    In a macro-enmabled workbook called TestClient.xlsm placed in same directory as the Debug output Dll I write the following in the ThisWorkbook module

    Option Explicit
    
    Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
    
    Private Sub Workbook_Open()
        '* next line establishes relative position of Dll
        Debug.Assert Dir(ThisWorkbook.Path & "\IDLForModules.dll") = "IDLForModules.dll"
    
        '* next line loads the Dll so we can avoid very long Lib "c:\foo\bar\baz\barry.dll"
        LoadLibrary ThisWorkbook.Path & "\IDLForModules.dll"
    
        '* next go to  Tools References are check "Idl For Modules"
        '* "Idl For Modules" Iis set in the IDL with helpstring("Idl For Modules")
    
    End Sub
    

    I then add a Tools Reference to the newly created Type library and now I can complete by adding a standard module and adding the following

    Option Explicit
    
    Sub TestAbs()
        Debug.Print IDLForModulesLib.Math.Abs(-5)
    End Sub
    
    Sub TestUpper()
        Debug.Print IDLForModulesLib.Strings.Upper("foobar")
    End Sub
    

    This works for me on Windows 8.1 Professional 64 bit, VS2013, Excel 15. Fuller instructions for C++ newbies can found here Throw away Declare Function with IDL for Modules.

提交回复
热议问题