tags:

views:

281

answers:

1

I have an issue with a third-party COM+ DLL meant to be used from VB6, where it has a function to set a Callback for a hardware event. However, I'm using VB.NET, and AddressOf now returns a reference type instead of an integral type, which means that the setCallback function on the COM+ DLL apparently can't be used.

Is there a way around this problem (I don't have VB6 available to develop some sort of wrapper with), or will I have to find a different 3rd-party DLL in order to get this to work? For reference, I'm trying to access the LCD on a Logitech G15(v2) keyboard.

For Reference, here is the setCallback function and the callback's prototype itself:

Public Sub setCallback(funcAddr As Integer)
Public Sub LCDbuttonPress(ByVal butStates As Integer)
+2  A: 

I think if you declare your setCallback function like this:

Public Sub setCallback([MarshalAs(UnmanagedType.FunctionPtr)]funcAddr as function)

I'm not a VB guy, so I don't know the exact syntax. But the basic idea here is that in VB.Net you declare the prototype as taking a delegate, even a delegate of the correct type. But then you use the MarshalAs attribute to tell the marshalling code to treat it as a function pointer (actually a Integer) on the other side. I do this in C# to pass callbacks to C++ code and it works just fine.

For instance this in C#

public delegate int MyProgress(double dPercentComplete);
...
int WaitWithProgress([MarshalAs(UnmanagedType.FunctionPtr)]MyProgress pfn);

Shows up on the C++ side of the house as this

HRESULT __stdcall WaitWithProgress (long pfn, int * pRetVal);

Note the comments. The actual solution to this problem turned out to be Marshal.GetFunctionPointerForDelegate() And be careful to read the docs on this. If you use this method, it becomes your responsibility to make sure that the delegate isn't garbage collected before you setCallback(NULL)

John Knoeller
The problem here is that setCallback is a function in the DLL, so I cannot change it or the function definition at all.
Sukasa
You aren't changing the the callback, you are just changing the prototype *as VB.NET sees it*. Then using MarshalAs to contol how it converts what VB.NET sees to what VB6 sees.
John Knoeller
John: As far as I can tell, VS2008 is taking the prototype for setCallback *from* the DLL, so what I'm saying is that as far as I understand I can't redeclare the callback with the MarshalAs parameter in place there. If I'm wrong, then I apologize for being difficult.
Sukasa
I suspect that there is some way to get it to use an alternate prototype. But I'm no VB guy, so I have no idea how to go about it.How about `Marshal.GetFunctionPointerForDelegate()`.
John Knoeller
Ah, thanks for the `Marshal.GetFunctionPointer...` note, that fixed it perfectly!
Sukasa