473,895 Members | 2,377 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C++/CLI, Unmanaged to Managed callback without using a bridge, or pinning pointers.

Hi,

I have a rather interesting problem. I have a unmanged c++ class
which needs to communicate information to managed c++ via callbacks,
with a layer of c# on top of the managed c++ ultimatley retreiving the
data. Presently all of the c++ code is still in .NET 1.1, so we're
using a _nogc bridge class wrapped in a _gc c++ class in order to
facilitate this interop.

But we've converted everything not c++ to .NET 2.0 and would love to
convert the c++ as well, but I'm not sure how to overcome this
problem. My issues...

1.) C++/CLI does not support this _nogc bridge class idea.

2.)I would need to have this pointer around for the life of the
application, which means I would need to pin it, which is a
ridiculously bad idea considering it will be locked on the heap for
the duration.

So I'm not sure how to overcome this. Any help would be greatly
appreciated.

Feb 9 '07 #1
12 12568
I have a rather interesting problem. I have a unmanged c++ class
which needs to communicate information to managed c++ via callbacks,
with a layer of c# on top of the managed c++ ultimatley retreiving the
data. Presently all of the c++ code is still in .NET 1.1, so we're
using a _nogc bridge class wrapped in a _gc c++ class in order to
facilitate this interop.

But we've converted everything not c++ to .NET 2.0 and would love to
convert the c++ as well, but I'm not sure how to overcome this
problem. My issues...

1.) C++/CLI does not support this _nogc bridge class idea.

2.)I would need to have this pointer around for the life of the
application, which means I would need to pin it, which is a
ridiculously bad idea considering it will be locked on the heap for
the duration.
Hi,

First of all, have you tried building your C++ code with /clr:oldSyntax?
That should enable you to port to .NET2.0 and VC2005 without doing anything,
save for a tweak here or there maybe.

I am not sure I understand (1) correctly. In C++/CLI you can still wrap a
managed class around a native class. Do you mean somehing else?

--

Kind regards,
Bruno van Dooren
br************* *********@hotma il.com
Remove only "_nos_pam"
Feb 9 '07 #2
On Feb 9, 1:04 am, "Bruno van Dooren [MVP VC++]"
<bruno_nos_pam_ van_doo...@hotm ail.comwrote:
I have a rather interesting problem. I have a unmanged c++ class
which needs to communicate information to managed c++ via callbacks,
with a layer of c# on top of the managed c++ ultimatley retreiving the
data. Presently all of the c++ code is still in .NET 1.1, so we're
using a _nogc bridge class wrapped in a _gc c++ class in order to
facilitate this interop.
But we've converted everything not c++ to .NET 2.0 and would love to
convert the c++ as well, but I'm not sure how to overcome this
problem. My issues...
1.) C++/CLI does not support this _nogc bridge class idea.
2.)I would need to have this pointer around for the life of the
application, which means I would need to pin it, which is a
ridiculously bad idea considering it will be locked on the heap for
the duration.

Hi,

First of all, have you tried building your C++ code with /clr:oldSyntax?
That should enable you to port to .NET2.0 and VC2005 without doing anything,
save for a tweak here or there maybe.

I am not sure I understand (1) correctly. In C++/CLI you can still wrap a
managed class around a native class. Do you mean somehing else?

--

Kind regards,
Bruno van Dooren
bruno_nos_pam_v an_doo...@hotma il.com
Remove only "_nos_pam"- Hide quoted text -

- Show quoted text -
Really? I was under the impression it wasn't supported. Would you
mind showing me an example with CLI syntax?

Feb 9 '07 #3
DaTurk wrote:
Really? I was under the impression it wasn't supported. Would you
mind showing me an example with CLI syntax?
http://tweakbits.com/UnmanagedToManagedCallback.cpp
http://tweakbits.com/ManagedToUnmanagedCallback.cpp

This is how you bridge managed and unmanaged code.

You should only pin an object for a very brief period of time, while
you're accessing or marshalling data. Under no circumstances should you
keep an object pinned for the entire lifetime of the application.

You can no longer put a nested unmanaged class inside a managed one, but
that's just syntax and style. From the technical standpoint, there's
practically nothing that you can't achieve without nested classes,
thanks to the public protected and internal access modifiers.

There is nothing in MC++ that C++/CLI can not do anymore (nesting is not
really a major feature, just a convenience). They just use a different
syntax. How did you solve pinning in your MC++ code? The rules are the
same in C++/CLI. How did you bridge unmanaged and managed classes? You
do exactly the same in C++/CLI, with a different syntax.

Tom
Feb 9 '07 #4
On Feb 9, 11:48 am, Tamas Demjen <tdem...@yahoo. comwrote:
DaTurk wrote:
Really? I was under the impression it wasn't supported. Would you
mind showing me an example with CLI syntax?

http://tweakbits.com/UnmanagedToMana...edCallback.cpp

This is how you bridge managed and unmanaged code.

You should only pin an object for a very brief period of time, while
you're accessing or marshalling data. Under no circumstances should you
keep an object pinned for the entire lifetime of the application.

You can no longer put a nested unmanaged class inside a managed one, but
that's just syntax and style. From the technical standpoint, there's
practically nothing that you can't achieve without nested classes,
thanks to the public protected and internal access modifiers.

There is nothing in MC++ that C++/CLI can not do anymore (nesting is not
really a major feature, just a convenience). They just use a different
syntax. How did you solve pinning in your MC++ code? The rules are the
same in C++/CLI. How did you bridge unmanaged and managed classes? You
do exactly the same in C++/CLI, with a different syntax.

Tom
OK, I see. But here's my question.

static void __stdcall CallbackForward er(void* param, int arg)
{
static_cast<Thu nk*>(param)->receiver->HandleEvent(ar g);
}
if this is a ,managed call. How is it the pointer not moving around.
How does it stay pinned? If I'm registering a managed delegate to an
unmanged class, how do I keep that pointer around for the life of the
application for all of the information flowinf back from unmanaged to
managed.

Thankd for that help, I really do appreciate it.

Feb 9 '07 #5
DaTurk wrote:
static void __stdcall CallbackForward er(void* param, int arg)
{
static_cast<Thu nk*>(param)->receiver->HandleEvent(ar g);
}
This is a snippet from my
http://tweakbits.com/UnmanagedToManagedCallback.cpp sample.
if this is a ,managed call. How is it the pointer not moving around.
How does it stay pinned?
In the above example, Thunk is not a ref class, it's a native class. It
doesn't require pinning. Remember, * is a native pointer, ^ is a managed
handle.
If I'm registering a managed delegate to an
unmanged class
Then you need to look at my other sample,
http://tweakbits.com/ManagedToUnmanagedCallback.cpp
how do I keep that pointer around for the life of the
application
Once again:

UnmanagedToMana gedCallback.cpp :
When your receiver is managed, it is gcroot-ed in the unmanaged sender
(the Thunk class, in my example). gcroot-ed classes are fully managed,
they don't require pinning. This is Microsoft's solution for embedding a
managed object inside an unmanaged one. The same gcroot template existed
back in the old MC++. There's no difference between MC++ and C++/CLI
here. The way it works is that the native class stores just a 32-bit (or
64-bit) handle to the managed object, but it's not an actual memory
address. When the object gets moved around, its handle value still stays
the same.

ManagedToUnmana gedCallback.cpp :
When your receiver is unmanaged, you don't have to pin that, since
unmanaged classes don't get moved.

Maybe you don't fully understand when pinning is required. You only pin
a managed object when you directly deal with its memory address. For
example:

array<int>^ arr = gcnew array<int>(10); // managed array
pin_ptr<intp = &arr[0]; // pin it
int* native_ptr_to_m anaged = p; // unmanaged pointer to the array
// Source: http://msdn2.microsoft.com/en-us/library/1dz8byfh.aspx

Note how in this example you are accessing a managed object's memory
address directly via an unmanaged pointer. This requires pinning, or
else the memory address of the managed object might change.

The value of a managed handle never changes, so it can be stored inside
a native object without pinning:

ref class Managed { };

class Native
{
[...]
gcroot<Managed^ managed;
};

If "managed" moves around, its handle value remains the same.

Tom
Feb 10 '07 #6
On Feb 9, 6:21 pm, Tamas Demjen <tdem...@yahoo. comwrote:
DaTurk wrote:
static void __stdcall CallbackForward er(void* param, int arg)
{
static_cast<Thu nk*>(param)->receiver->HandleEvent(ar g);
}

This is a snippet from myhttp://tweakbits.com/UnmanagedToMana gedCallback.cpp sample.
if this is a ,managed call. How is it the pointer not moving around.
How does it stay pinned?

In the above example, Thunk is not a ref class, it's a native class. It
doesn't require pinning. Remember, * is a native pointer, ^ is a managed
handle.
If I'm registering a managed delegate to an
unmanged class

Then you need to look at my other sample,http://tweakbits.com/ManagedToUnmanagedCallback.cpp
how do I keep that pointer around for the life of the
application

Once again:

UnmanagedToMana gedCallback.cpp :
When your receiver is managed, it is gcroot-ed in the unmanaged sender
(the Thunk class, in my example). gcroot-ed classes are fully managed,
they don't require pinning. This is Microsoft's solution for embedding a
managed object inside an unmanaged one. The same gcroot template existed
back in the old MC++. There's no difference between MC++ and C++/CLI
here. The way it works is that the native class stores just a 32-bit (or
64-bit) handle to the managed object, but it's not an actual memory
address. When the object gets moved around, its handle value still stays
the same.

ManagedToUnmana gedCallback.cpp :
When your receiver is unmanaged, you don't have to pin that, since
unmanaged classes don't get moved.

Maybe you don't fully understand when pinning is required. You only pin
a managed object when you directly deal with its memory address. For
example:

array<int>^ arr = gcnew array<int>(10); // managed array
pin_ptr<intp = &arr[0]; // pin it
int* native_ptr_to_m anaged = p; // unmanaged pointer to the array
// Source:http://msdn2.microsoft.com/en-us/library/1dz8byfh.aspx

Note how in this example you are accessing a managed object's memory
address directly via an unmanaged pointer. This requires pinning, or
else the memory address of the managed object might change.

The value of a managed handle never changes, so it can be stored inside
a native object without pinning:

ref class Managed { };

class Native
{
[...]
gcroot<Managed^ managed;

};

If "managed" moves around, its handle value remains the same.

Tom
OK, I put a post in the main forum, but I was curious if you knew. I
see what your saying. So I moved my native bridge class outside of
the managed class. Now to make it work, I have the bridge class
contain a gcrooted reference to my managed class. But I want it to be
static, but I get a couple linker errors. Apparently you can't have a
static gcrooted managed variable in a native class. Do you know of
any work around?

Feb 13 '07 #7
DaTurk wrote:
But I want it to be
static, but I get a couple linker errors. Apparently you can't have a
static gcrooted managed variable in a native class. Do you know of
any work around?
What's the exact error? Have you initialized the gcroot? You have to
initialize it in your .cpp file, like this:

// .h
ref class Managed { };

class Native
{
static gcroot<Managed^ managed;
};

// .cpp
gcroot<Managed^ Native::managed (gcnew Managed);

Tom
Feb 13 '07 #8
I'll fiddle with it, I was getting a linking error. I was using
something similar to this

msclr::auto_gcr oot<ManagedRece iver^receiver;

and as soon as I threw static in front it was not happy.

On another note, I've found a different solution to the problem and I
was hoping you could help explain exactly what is going on.

So, my problem is that I have a native class that needs to
communicate, via callbacks, asynchronously to a managed C++/CLI class,
which then communicates to C#.

Originally with MC++ we were using the bridge class, and now that
we've moved, or are moving to CLI we need to find a different
approach. So while I was fiddling, I did this. I just included a
seperate function outside of the managed class in a seperate
namespace. And it uses the managed class static reference to itself
to invoke it's callbacks, and it works. But why has no one mentioned
this before? It's the best solution I;ve seen yet, what's wrong with
it? Here's some code.
namespace ManagedLib
{
[StructLayout(La youtKind::Seque ntial, CharSet=CharSet ::Ansi, Pack=8)]
public ref struct MStruct
{
public:
System::Int32 x;
System::Int32 y;

[MarshalAs(Unman agedType::ByVal TStr, SizeConst=50)]
System::String^ str;

virtual String^ ToString() override
{
return String::Format( "X:{0} Y:{1} STR:
{2}",Convert::T oString(x),Conv ert::ToString(y ),str);
}
};

public delegate void DataChangedEven tHandler(MStruc t^ item);

public ref class MClass
{
private:
UnmanagedLib::U Class* pUnmanagedClass _ ;

public:
MClass()
{
pUnmanagedClass _ = new UClass(); //unmanaged heap
//pUnmanagedClass _-
>RegisterUnmana gedCallBack(&(_ UClassBridge::U nmanagedBridgeC allback));
pUnmanagedClass _-
>RegisterUnmana gedCallBack(&(U nmanagedCallbac kMethods::Unman agedBridgeCallb ack));
pMe_ = this;
}

~MClass(){
delete pUnmanagedClass _;
};

static MClass^ pMe_ = nullptr;
DataChangedEven tHandler^ pManagedDelegat e_;

void RunSimulation()
{
MStruct^ item = gcnew MStruct();
item->x = 1;
item->y = 2;
item->str = "Test";

for(int i = 0;i< 100000;i++)
{
item->x = i+1;

UStruct uItem;
Marshal::Struct ureToPtr(item, (System::IntPtr )&uItem, true);

pUnmanagedClass _->FireUnmanagedC allback(uItem);
Thread::Sleep(1 00);
}
}
};
}

namespace UnmanagedCallba ckMethods
{
static void UnmanagedBridge Callback(const UStruct item)
{
Console::WriteL ine("UnmanagedB ridgeCallback: Fired");

UStruct uItem = item;
ManagedLib::MSt ruct^ mItem = gcnew ManagedLib::MSt ruct();
Marshal::PtrToS tructure((Syste m::IntPtr)&uIte m, mItem);

ManagedLib::MCl ass::pMe_->pManagedDelega te_->Invoke(mItem );
}
};

Thanks again for all the help.

Feb 13 '07 #9
DaTurk wrote:
But why has no one mentioned this before?
Because your solution only works with singleton classes. As soon as you
have two objects in the memory, it stops working. My original example
didn't have that restriction. It was generic enough to track an
unlimited number of objects.

Of course, use what fits your needs. Glad you've worked it out.

Tom
Feb 13 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
2347
by: Bruce Farmer | last post by:
I am having problems accessing a managed object from unmanaged code. Specifically, I have a .NET forms application with a web service proxy. The forms application links to an unmanaged DLL which uses callbacks to receive data via TCP. The data received in the callback must be passed to a web service via a web method provided by the proxy. So the callback (which is unmanaged code) needs to access the proxy (managed object) to send the...
3
3517
by: zhphust | last post by:
I want to convert a object of a managed class to a unmanaged structure that has the same member with that managed class. Can anybody tell me how i can do it? Thanks in advance. -- zhphust ------------------------------------------------------------------------
10
5170
by: Bonj | last post by:
I use the following code to convert a managed string to an unmanaged one: _TCHAR error; const char* umstring = (const char*)Marshal::StringToHGlobalAnsi (merror).ToPointer(); _tcscpy(error, umstring); Marshal::FreeHGlobal(IntPtr((void*)umstring)); I can't use StringToHGlobalAuto because it only ever returns the first character.
4
5729
by: William F. Kinsley | last post by:
My understanding is that when I re-compile a existing MFC application with the /clr switch, that the code generated is managed(with some exceptions) but that the data isn't, i.e. not garbage collected. I also noticed that when replaced some of the existing MFC dialogs with managed winforms that everything is still running in the same app domain.( No context change) So my question is this, what are the performance differences in using...
2
1703
by: Sasha Nikolic | last post by:
I have one unmanaged and one managed class in the same vc++ project. Managed object creates one instance of unmanaged class and needs to pass a callback reference so that unmanaged class can periodically call the managed class's method (without holding the reference to the managed object). Can anybody please provide me with a short example or a basic idea? Thanks a lot, Sasha
1
2391
by: quat | last post by:
I have two unmanaged pointer in a managed form class: IDirect3D9* d3dObject; IDirect3DDevice9* d3dDevice; In a member function of the form, I call: d3dObject->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
7
6442
by: DaTurk | last post by:
Hi, I'm coding up an application that has a native c++ layer, asynchronously calling callback in a CLI layer. We originally did this with static inline methods in the CLI layer, but this solution only works with singleton objects. So I have to explore other solutions. So beside pinning pointers, I've been looking at GCHandle. I was
20
2317
by: =?Utf-8?B?VGhlTWFkSGF0dGVy?= | last post by:
Sorry to bring up a topic that is just flogging a dead horse.... but... On the topic of memory management.... I am doing some file parcing that has to be done as quick as posible, but what I have found hasnt been encouraging... I found that the *quickest* way is to use a struct to retrieve fixed length packets out of the file, but structs get placed on the stack! In one of the books I read, the stack is only about 1mb, so I would...
9
3569
by: =?Utf-8?B?RWR3YXJkUw==?= | last post by:
I would greatly appreciate some help on passing managed object into unmanaged code. I need to pass a reference (address of) of a managed class into unmanaged code (written by a thrid party). The 3rd party unmanaged DLL will pass this reference into standard Win32 unmanaged static callback function in my code. Inside this unmanaged callback function I need to cast this unmnaged pointer that I have received from 3rd party back into the...
0
9990
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10845
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10935
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10473
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
8028
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5863
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4689
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4285
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3294
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.