Callbacks from unmanaged to managed C++

D

DavidT

Hello,

at first, exuse if the following question is simple to solve, but i
normaly coding with C# and now have to use C++/CLI for one project.

My Problem is that i have to use a native c++ sdk to read pictures
from ip cameras. I get the native c++ decoder worked so far and now
try to send callbacks from unmanaged to managed code, to signal wenn a
picture is fully received.

To get a first view on that area i implemented a little test where i
extract a pointer from a delegate and sending the pointer to unmanaged
code. In the unmanaged function i use the callbackfunction (after
filling an array), jump back to to managed code and marshaling the
generated array to the managed world.
That little example is working fine in debugmode but as soon as i
running in releasemode the programm crashs and i dont know why.

So, at first my Code:
Code:
#include <iostream>
#pragma unmanaged
class umTest
{
private:
unsigned char * data;
public:
void Caller(int size, void callback(int, unsigned char*))
{
data = new unsigned char[size];
for(int i = 0; i < size; i++)
data[i] = i;
callback(size,data);
};

};
#pragma managed

#pragma managed
using namespace System;
using namespace System::Runtime::InteropServices;

public delegate void callback(int, unsigned char*);

ref class mTest
{
private:
array<unsigned char> ^destination;
int size;

public:
mTest()
{
callback ^d = gcnew callback(this,&mTest::callTest);
IntPtr ptr = Marshal::GetFunctionPointerForDelegate(d);
umTest *umT = new umTest();
[B]umT->Caller(5,
static_cast<void (__cdecl *)(int, unsigned char*)>
(ptr.ToPointer()));
this->print();
}

void callTest(int size, unsigned char* test)
{
this->size = size;
destination = gcnew array<unsigned char>(size);
Marshal::Copy(IntPtr(test),destination,0,size);
delete[](test);
test = NULL;
this->print();
};

void print()
{
for(int i = 0; i<size; i++)
Console::WriteLine("destination[{0}]={1}",i,destination[i]);
};
};
When it runs in release mode, the callbackfunction is normally called
but after finishing the function, he is called again. On the
Marshal::Copy(...)-Line then the programm is crashing without any
exception...

I hope someone of you find the mistake, i have no idea anymore...
Thanks in advance

Greets,

David
 
J

Jochen Kalmbach [MVP]

Hi DavidT!

My Problem is that i have to use a native c++ sdk to read pictures
from ip cameras. I get the native c++ decoder worked so far and now
try to send callbacks from unmanaged to managed code, to signal wenn a
picture is fully received.

Normally callbacks to managed code are done via "gcroot" Template...
See:
http://groups.google.de/group/microsoft.public.dotnet.languages.vc/msg/577d07f3522b5a25?hl=de&

--
Greetings
Jochen

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

DavidT

Hi DavidT!


Normally callbacks to managed code are done via "gcroot" Template...
See:http://groups.google.de/group/microsoft.public.dotnet.languages.vc/ms...

--
Greetings
Jochen

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

At first, thanks for your answer here and at the german c++-board. I
tried it now with gcroot but i have the problem (sorry, i realy new to
C++/CLI) that i can't set my managed class via a setter-method.

Here my code:

using namespace System;
using namespace System::Runtime::InteropServices;

#include <msclr\auto_gcroot.h>

ref class mClass
{
void callback()
{

};
};

class umClass
{
public:
msclr::auto_gcroot<mClass^> mClass;

void setCallback()
{

};
};

What is the type of my setCallback parameter? mClass*? pointers on
unmanaged classes are not allowed in C++/CLI, are they? mClass^?
Trakinghandles also not available in native code. In your example it
absolutly clear, but what have i to do in the new C++/CLI?

The other Problem is, it doesnt matter what i try, i get all the time
the following error:

Fehler 2 error C2327: 'umClass::mClass': Ist kein Typname, nicht
statisch und kein Enumerator
19 (engl. mClass is no typename, not statical and no enum)

What is my mistake?

Thanks again,

David
 
J

Jochen Kalmbach [MVP]

Hi DavidT!
ref class mClass
{
void callback()
{

};
};

class umClass
{
public:
msclr::auto_gcroot<mClass^> mClass;

void setCallback()
{

};
};

void setCallback(mClass^ o)
{
mClass = o;
}

and

void doCallback()
{
mClass ^o;
o->callback();
}


--
Greetings
Jochen

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

Jochen Kalmbach [MVP]

void doCallback()
{
mClass ^o;
o->callback();
}

Upps... should be:

class umClass
{
public:
msclr::auto_gcroot<mClass^> _m;

void setCallback(mClass^ o)
{
_m = o;
};
void doCallback()
{
mClass ^o;
o = _m;
o->callback();
}
};

--
Greetings
Jochen

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

DavidT

Hi DavidT!






void setCallback(mClass^ o)
{
mClass = o;

}

and

void doCallback()
{
mClass ^o;
o->callback();

}

--
Greetings
Jochen

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

i splitted up both classes into different files.

When i do your changed i get the same error (your german, so i keep
translation:


Fehler 3 error C2327: 'umClass::mClass': Ist kein Typname, nicht
statisch und kein Enumerator 11

Fehler 4 error C2065: 'o': nichtdeklarierter Bezeichner 18

Fehler 5 error C2227: Links von "->callback" muss sich ein Zeiger auf
Klassen-/Struktur-/Union-/generischen Typ befinden. 19

Is there something wrong with my vs settings?!?

Thanks a lot,

David
 
D

DavidT

Fehler 3 error C2440: '=': 'msclr::auto_gcroot<_element_type>' kann
nicht in 'mClass ^' konvertiert werden 18


o = _m.get(); <- is it this?

Sorry, i don't wanna get you on your nerves but i absolutely running
out of concentration after weeks trying to pass this (obviously
simple) problem...

Thanks,

David
 
D

DavidT

Ok, it's working now! Thanks a lot, i still dunno where my initial
mistake was but thats not sooo important rigth now :)

A addition question to you, if allowed:

When i produce a unsigned char array in my native class and want to
copy the whole array to the unmanaged world and send it to a
memorystream, is it enough to submit the pointer from umngt to mngt an
copy the data to the stream? Or have i to marshal it first du a mngt-
array and then send to the memory-stream?

Thanks,

David
 
J

Jochen Kalmbach [MVP]

Hi DavidT!
When i produce a unsigned char array in my native class and want to
copy the whole array to the unmanaged world and send it to a
memorystream, is it enough to submit the pointer from umngt to mngt an
copy the data to the stream? Or have i to marshal it first du a mngt-
array and then send to the memory-stream?

You mean somthing like this:

array<Byte> ^arr;
Then you can pin it...

array<Byte> ^bDst = gcnew array<Byte>(10);
pin_ptr<Byte> pDstPinned = &bDst[0];

Then you can use the "pinned" array and access it like a native array...

For example:

#using <mscorlib.dll>
#include <memory.h>

#include <mscoree.h>
using namespace System;

int main()
{
array<Byte> ^bDst = gcnew array<Byte>(10);

unsigned char *pSrc = new unsigned char[10];
for(size_t i=0; i<10; i++)
pSrc = i;
{
pin_ptr<Byte> pDstPinned = &bDst[0];
memcpy(pDstPinned, pSrc, 10);
}

for each (Byte b in bDst)
Console::WriteLine(b);
}



--
Greetings
Jochen

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

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