Re: VB function called from c++
"Jake" wrote:
I have a C++ function that calls a VB dll but I am not
that familiar
with VB in order to resolve the crash that I am having.
This is my code
int u_dll_imstest_call(wchar_t *TheConnectString, wchar_t
*TheTable,
wchar_t *TheFields, wchar_t *ThePopupTitle, wchar_t
*TheOrderBy,
wchar_t *TheWhereClause, wchar_t *ThePosition)
{
// Declare an HRESULT and a pointer to the
clsVBTestClass interface
HRESULT hr;
BSTR bTheConnectString = L"Provider =
Microsoft.Jet.OLEDB.4.0;Data
Source=C:\\Imstestfor8.2\\database\\CAT16.mdb";
BSTR bTheTable = L"USR";
BSTR bTheFields =
L"USERNAME,Name,USER_ID,ID,U_LOGIN,Log-in";
BSTR bThePopupTitle = L"User Table";
BSTR bTheOrderBy = L"USERNAME";
BSTR bTheWhereClause = L"!=0000000001";
BSTR bThePosition = L"b";
You cannot use BSTR like that. In order to be valid BSTR
must be allocated with `SysAllocString' function call. There
are many C++ wrappers for BSTR out there in the world.
`_bstr_t' class is one of them. Just use it instead of raw
BSTR. Where `BSTR*' type is required call
`_bstr_t::GetAddress' to get a pointer to contained BSTR.
_bstr_t value;
_clsCat16 *IclsCat16 = NULL;
// Now we will intilize COM
hr = CoInitialize(0);
// Use the SUCCEEDED macro and see if we can get a pointer
// to the interface
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(__uuidof (clsCat16),
NULL,
CLSCTX_INPROC_SERVER,
_uuidof (_clsCat16),
(void**) &IclsCat16);
// If we succeeded then call the CountStringLength method,
// if it failed then display an appropriate message to the
user.
if(SUCCEEDED(hr))
{
value = IclsCat16->Popup(&bTheConnectString, &bTheTable,
&bTheFields, &bThePopupTitle,
&bTheOrderBy, &bTheWhereClause,
&bThePosition);
return 0;
^^^^^^^^
BUG! Because of this `return' statement `IclsCat16'
interface is never released, therefore it's leaked. Also,
call to `CoUninitialize' is unreachable.
}
else
{
}
}
// Uninitialize COM
CoUninitialize();
return 0;
}
I am using #import "WFCat16.dll" no_namespace in order to
import the
tlh file
This is what the function looks like in the tlh
struct
__declspec(uuid("21eb71ba-4e5f-4948-9315-b38c29fd296c"))
_clsCat16 : IDispatch
{
//
// Wrapper methods for error-handling
//
_bstr_t Popup (
BSTR * TheConnectString,
BSTR * TheTable,
BSTR * TheFields,
BSTR * ThePopupTitle,
BSTR * TheOrderBy,
BSTR * TheWhereClause,
BSTR * ThePosition );
//
// Raw methods provided by interface
//
virtual HRESULT __stdcall raw_Popup (
/*[in,out]*/ BSTR * TheConnectString,
/*[in,out]*/ BSTR * TheTable,
/*[in,out]*/ BSTR * TheFields,
/*[in,out]*/ BSTR * ThePopupTitle,
/*[in,out]*/ BSTR * TheOrderBy,
/*[in,out]*/ BSTR * TheWhereClause,
/*[in,out]*/ BSTR * ThePosition,
/*[out,retval]*/ BSTR * _arg8 ) = 0;
};
Look further in generated .TLH file. There should be smart
pointer wrapper declaration for `_clsCat16' class. Look for
"_COM_SMARTPTR_TYPEDEF(_clsCat16)" declaration or similar.
Just try to use `_clsCat16Ptr' instead of raw interface.
Using smart pointer wrapper will reduce places of potential
errors in your code. Usually you don't need to create COM
object's instance with call to `CoCreateInstance' when smart
pointers generated by `#pragma' directive are used. You
create it like that:
_clsCat16Ptr ptrCat16(__uuidof(clsCat16));
Then use it as regular pointer:
_bstr_t btRet = ptrCat16->Popup(...);
I guess my question is am I right in defining my input as
BSTR and then
sending the address of the data to the VB function?
No, you didn't allocate BSTR properly. Either use C++
wrappers like `_bstr_t' or Win32 API functions like
`SysAllocString'.
I am using _bstr_t to define my return value because that
is how it
should be returned from the VB call - Do I need to
allocate the _bstr_t
field before I use it?
No allocation is required here. `_bstr_t' class will perform
all necessary acclocations for you.
Eventually I want to take wchar_t * values and send them
to this
function but for right now I just trying to get it to
work - Anybody
have any ideas?
`_bstr_t' instance can be contructed from `wchar_t*' without
any problem:
wchar_t* pwsz = L"Hello!";
_bstr_t bt(pwsz); // bt contains "Hello!" now
HTH
Alex