Call back function and VC 2005

G

Guest

I have a DLL written in C++ (unmanaged), which I want to inteface with.

I created a standard window form program with VC++ 2005, all fine
I have imported an .h file the .lib file and all works.

/clr is on so I am writing managed code.

the problem comes when I need to use a function of the DLL with a callback
function parameter. (address of a function)

No way to get it compiled due to managed code restrictions.

I can get it working with /clr:noAssembly but i'd rather use managed code.

I think that I need to use delegate? correct?

I did not found any example, anyone can help me?



Many Thanks,

Filippo
 
J

Jochen Kalmbach [MVP]

Hi Filippo!
I have a DLL written in C++ (unmanaged), which I want to inteface with.

I created a standard window form program with VC++ 2005, all fine
I have imported an .h file the .lib file and all works.

/clr is on so I am writing managed code.

the problem comes when I need to use a function of the DLL with a callback
function parameter. (address of a function)

No way to get it compiled due to managed code restrictions.

?

There are two ways:

1. Using Explicit PInvoke
http://msdn2.microsoft.com/en-us/library/eyzhw3s8.aspx

Here is a small example for WinAPI "EnumWindows":

delegate int EnumWindowsDelegate2(int hWnd, int lParam);

[System::Runtime::InteropServices::DllImportAttribute("user32.dll",
EntryPoint="EnumWindows")]
static int MyEnumWindows(EnumWindowsDelegate2^ callback, int lParam);

void button2_Click(System::Object^ sender, System::EventArgs^ e)
{
sb = gcnew System::Text::StringBuilder();
MyEnumWindows(gcnew EnumWindowsDelegate2(this, &Form1::MyCallback2), 0);
MessageBox::Show(sb->ToString());
}
System::Text::StringBuilder ^sb;
int MyCallback2(int hWnd, int lParam)
{
sb->AppendFormat("{0}\r\n", hWnd);
return 1;
}


2. More sophisticated way with a struct (but needs to be compiled with
/clr only!):
(Same example as above):

delegate bool EnumWindowsDelegate1(HWND hWnd);
struct EnumWindowsCallback
{
EnumWindowsCallback(EnumWindowsDelegate1 ^d) : del(d) {}
gcroot<EnumWindowsDelegate1^> del;
bool Execute()
{
EnumWindows(&MyEnumWindowsCallback, (LPARAM) this);
return true;
}
static BOOL CALLBACK MyEnumWindowsCallback(HWND hWnd, LPARAM lParam)
{
EnumWindowsCallback *pThis = (EnumWindowsCallback*) lParam;
bool bRet = pThis->del->Invoke(hWnd);
if (bRet == true)
return TRUE;
return FALSE;
}
};

void button1_Click(Object^ sender, EventArgs^ e)
{
sb = gcnew System::Text::StringBuilder();
EnumWindowsCallback m(gcnew EnumWindowsDelegate1(this,
&Form1::MyCallback1));
m.Execute();
MessageBox::Show(sb->ToString());
}

System::Text::StringBuilder ^sb;
bool MyCallback1(HWND hWnd)
{
int i = (int) hWnd;
sb->AppendFormat("{0}\r\n", i);
return true;
}

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
L

Laurent Lequenne

I got the same problem last week... and finally decided to get the
information from MSDN. Miracle I found the info... Not exactly where
expected... But I found it, if you know that you need to use the Interop
namespace it can help to find out the information, but I don't know exactly
where I found the info. Anyway That piece of code should work... Important
thing is the GetFunctionPointerForDelegate, it returns a pointer that is not
locked in the GC. You need to use the GCHandle::Alloc function to lock that
delegate :)

// Delegate Declaration
delegate prResponse CamCallBackFuncDelegate(prHandle CameraHandle,prContext
Context,prVoid* pEventData);

// Your Code

CamCallBackFuncDelegate ^del = gcnew CamCallBackFuncDelegate(this,
&CanonSDK::RemoteCapture::CamCallBackFunc);

// Locks the delegate from the GC ?

GCHandle gch = GCHandle::Alloc(del);

// Get Pointer and SET unmanaged callback function

IntPtr ip = Marshal::GetFunctionPointerForDelegate(del);
prSetEventCB* cb = static_cast<prSetEventCB *>(ip.ToPointer());

// Callback setup

cErr = PR_SetEventCallBack( m_hCamera,(prContext) 1234,(prSetEventCB*) cb );
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top