Backstory: I'm working on bridging a 64 bit process to a 32 bit DLL using a COM object.
Why? Good question. It's not currently feasible to recompile all the x86 source to x64, unless there's absolutely no way around it...enter IPC.
I know it's not going to perform as well; making it work is my current task...I assume once it's seen that it doesn't perform as well, I'm going to be told to recompile all the x86 source anyway.
What's cool, though, is that it works with the testbed I've built. I'm having problems bringing it up to scale, however.
I am very unfamiliar with COM -- in fact the beginning of this week, Apr. 16, 2018 is literally the first time I've ever done anything with it.
I've got three pieces: the x64 exe, the x86 -> x64 surrogate exe, and an x86 .dll
the x64 exe seems to work fine:
CoInitialize(NULL);
CLSID clsid;
Ix86LibraryProxy* pProxy;
HRESULT hr = CLSIDFromProgID(OLESTR("x86x64.x86LibraryProxy"), &clsid);
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_Ix86LibraryProxy, (void **) &pProxy);
hr = pProxy->Load(HandleToLong(FindWindow(szWindowClass, szTitle)));
CoUninitialize();
This is the x86 -> x64 surrogate exe
// header file declaration
STDMETHOD(Update)(const float& dt, HRESULT* hResult);
//cpp file
STDMETHODIMP Cx86LibraryProxy::Update(const float& dt, HRESULT* hResult)
{
typedef HRESULT(*DLL_Update)(const float& dt);
*hResult = S_OK;
HMODULE hLib = LoadLibrary(L"DLL.dll");
if (hLib != NULL)
{
DLL_Update pFunc = (DLL_Update) GetProcAddress(hLib, "Update");
if (pFunc != NULL)
{
*hResult = (*pFunc)(dt);
}
else
{
*hResult = E_FAIL;
}
}
else
{
*hResult = E_INVALIDARG;
}
FreeLibrary(hLib);
return S_OK;
}
This is an export from the x86 dll
//x86 dll export
__declspec(dllexport) HRESULT Update(const float& dt)
Pretty standard runtime application stuff. The .dll has a function in it that takes in a const float& dt
and returns an HRESULT
.
Obviously at scale I wouldn't unload & reload the DLL every time I call this function.
In my .idl file I have the following:
interface Ix86LibraryProxy : IDispatch{
[id(1)] HRESULT Load([in] LONG hWnd, [out, retval] HRESULT* hResult);
[id(2)] HRESULT Update([in] const float& dt, [out, retval] HRESULT* hResult);
[id(3)] HRESULT Render([out, retval] HRESULT* hResult);
};
with compiler error Error 1 error MIDL2025: syntax error : expecting a declarator or * near "&"
I've see that MIDL doesn't support c++ constructs, but what I don't see is a way around it.
Any changes to the signature in the .idl file ([id(2)] HRESULT Update([in] const float dt, [out, retval] HRESULT* hResult);
) generates this error: Error 1 error C2259: 'ATL::CComObject<T>' : cannot instantiate abstract class
I see this question asks a similar one, but the answer to it doesn't feel like it answers the question, since it doesn't do anything with the MIDL file: https://stackoverflow.com/a/3028861/4518677
Since it doesn't appear that MIDL supports passing by reference, what would be a way around this?
What I also don't understand is that if the project for the x86 dll isn't under the same solution as the x86 -> x64 surrogate process, the x86 -> x64 surrogate process can't find the module when it tries to LoadLibrary("DLL.dll")
with GetLastError() == 126