I\'m really confused about passing strings from VBA to C++. Here\'s the VBA code:
Private Declare Sub passBSTRVal Lib \"
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.