How to pass managed reference to unmanaged code in C++/CLI? - visual-studio

I'm using C++/CLI only to unit test unmanaged C++ code in VS2010. I switched the compiler to /clr and using the unmanaged code from a static library.
I have a simple int property in my test class.
I would like to pass that as a const int & to a function in native C++. But it can't compile and I've found out that, it's because you can't mix references like that.
What is the way to do it, I tried to following and it's working, but is there a nicer way?
[TestClass]
public ref class MyTestClass
{
private:
int _my_property;
public:
[TestMethod]
void MyTestMethod()
{
MyNativeClass c;
// c.SomeMethod(_my_property) this doesn't work
int i = _my__property;
c.SomeMethod(i) // this works
}
}

C++ references are really just syntactic sugare for pointers. A C++ pointer points to a specific point in memory, while CLI references can be freely moved around by the garbage collector. To pass a reference to an object in managed memory to unmanged code, you need to pin the pointer.
More info and sample in another SO question: Convert from C++/CLI pointer to native C++ pointer
Edit 2
I'm removing the additional information, since it is obviously wrong (thanks #Tergiver and #DeadMG for your comments). I'm also making the post community wiki, so feel free to add any additional correct information.

Related

SmartPointer from DLL: where to construct & destruct

I'm currently remodelling a dynamic library project and removed a lot of STL and other dependencies from its header resulting in conflicting implementations between different toolchains.
The DLL Interface now only contains plain C-types and custom types whom implementation depends solely on the DLL code. But now I'm stuck with two remaining points.
The DLL should return some sort of reference counting smart pointer (with a weak pointer option)
Managing construction and destruction between the DLL boundaries. This more or less looks like this.
.
#include <memory>
class Config;
typedef std::shared_ptr<Config> ConfigPtr;
class CONFIGAPI_DLL Config
{
public:
///...
ConfigPtr getNewNode( char const* query = "." )
{
// construct obj in dll, but construct shared_ptr in header
return ConfigPtr( _constructgetNewNode(query) );
}
ConfigPtr getNewNodeFromHeader( char const* query = "." )
{
// construct obj and shared_ptr in header
auto obj = new Config;
obj->_init(query);
return ConfigPtr( obj );
}
private:
Config* _constructNewNode( char const* query = "." );
void _init( char const* query = "." );
};
I was thinking by creating the share_ptr at the dll headers (getNewNode) it would prevent mixed implementations of std::shared_ptr ...but I don't know if that is a good idea?
But I also construct the new object inside the DLL (_constructNewNode) and this means it should also be destructed there?
I tried to construct it in the headers and so in the user code scope (getNewNodeFromHeader)... this shouldn't cause problems?
The downside is I still export the C++11 header and rule out all older compilers. Is it possible to export the shared_ptr type from the dll as unconflicting code but still be compatible with std::shared_ptr?
thanks!
I suppose you want to mix creation and destruction of the objects (Config and the shared_ptr). If the DLL client is not compiled with the same version and configuration of the compiler you would be in troubles (for example, mixing debug and release modules). The main problem I see here: there is not any type of standard ABI for C++.
I was thinking by creating the share_ptr at the dll headers
(getNewNode) it would prevent mixed implementations of std::shared_ptr
...but I don't know if that is a good idea?
If you define your header file to create the shared_ptr, that would be OK if only a module use that header file. I mean, if the shared_ptr is not to be used for the content of the DLL, for example. BUT if other client module (a binary module, like other DLL) use also that header, you must be sure they are compiled with the same compiler and compiling configuration. If you have not that guarantee, then is not good idea.
But I also construct the new object inside the DLL (_constructNewNode)
and this means it should also be destructed there?
If you construct the object inside the DLL, you'll be better destroying inside the DLL. How to do that? specifying a deleter at shared_ptr construction. Something like
struct ConfigDeleter {
void operator()(Config* c) {
c->destroy(); // or as you want to implement it.
};
typedef std::shared_ptr<Config, ConfigDeleter> ConfigPtr;
I tried to construct it in the headers and so in the user code scope
(getNewNodeFromHeader)... this shouldn't cause problems?
As before, it depends if you can guarantee all modules are homogeneous (same compiler version and configuration, library, etc.). But of you want to implement as that, do it well:
// construct obj and shared_ptr in header
auto obj_ = make_shared<Config>();
obj_->init(query);
It is exception-safe and more efficient: just one allocation to store the object and the reference, instead two allocations in your sample.
If you want your code be safe for mixing modules, implement all allocations (shared_ptr included) into the DLL, if they are shared. Exports a "C" interface, and create header file to wrap that interface in classes. Something like:
class WConfig {
public:
WConfig(): m(IDll->create()) {
}
// other member functions as interface stub
~WConfig() {
IDll->release(m);
}
private:
Config* m;
};
To share this object, you can use copy constructor (that copy the pointer and call to IDll->reference(m), for example) or any other approach.

Calling a property on the const reference

I have C++/CLI class that defines a property:
public ref class AbstractOffer
{
public:
AbstractOffer();
property String^ Body;
};
In some function the AbstractOffer class is passed by const ref
foo(const AbstractOffer^ ao)
{
ao->Body;
}
When I call the property the method compiler gives the following error :-
error C2662: 'ivrworx::interop::AbstractOffer::Body::get' : cannot
convert 'this' pointer from 'const ivrworx::interop::AbstractOffer'
to 'ivrworx::interop::AbstractOffer %' 1> Conversion loses
qualifiers
It seems somehow connected to const. How can I call the Body property of the object if the object reference is passed by const?
The const qualifier is a problem in C++/CLI. It is only meaningful when it can be checked and that's not in general possible in .NET. It is of course not a problem when you only have one kind of compiler and that compiler follows strict language rules. Like C++. But .NET supports many languages, your method could be easily called from a Cobol.NET program for example. The odds of ever getting const-correctness added to the Cobol language are zero.
The compiler does compile code with const qualifiers and does make an effort to check when it can. Which is why you got the diagnostic. That can even work when the declaration exists in another assembly, as long as it was compiled with C++/CLI, the compiler emits modopt annotations in the metadata.
But there are limitations with that. Properties are one of them, you can't add the const qualifier to the getter, or a member function in general, you'll get slapped with C3842.
Best thing to do is to use C++/CLI for what it is good at, it is an interop language. And const qualifiers just don't work well in an interop scenario.
The only way I know to get round this is the cast away the const-ness. As long as you don't modify the object, it should be fine. (If you do modify it, I've no idea what the outcome will be).
i.e. change your function to be
void foo(const AbstractOffer^ ao)
{
const_cast<AbstractOffer^>(ao)->Body;
}

Handling metro event in native c++ class

I would like to handle a button clicked event in a native c++ class. I have tried creating a 'handler' object derived from Object to handle the event and then calling a c++ method. For example I tried the following code:
ref class GButtonHandler sealed : public Object
{
public:
void Button_Click(Object^ sender, RoutedEventArgs^ e)
{
}
GTextBlockHandler(GButtonImpl * pButtonImpl, Button ^ button)
{
button->Click += ref new RoutedEventHandler(this, &GTextBlockHandler::Button_Click);
}
};
Thinking that I could squirrel away the pButtonImpl pointer and then use it to call a native function in the Button_Clicked function. However on compiling this code, I get the error:
error C3986: '{ctor}': signature of public member contains native type 'GButtonImpl'
So it seems that it does not like me passing in native classes into an ref object. Is there a way to do this?
Note that I am completely new to developing Metro style apps, so bear with me!
Ok, it all makes sense to me now. For anyone else who is interested, the reason you cannot have WinRT Objects with public functions that have native C++ arguments is that these objects would then not be consumable by non C++ code. However, the (obvious?) solution is to make the constructor private and have the class that creates the Object declared as a 'friend' class (duh!). Then all is well, the compiler is happy, and I am happy.
Thanks to all who took the time to read this.
The correct answer is to use internal rather than public for the constructor. This tells the compiler that it will only be available in the current project, and won't be available to external projects (i.e. a library written in another language).

C++/CLI Resource Management Confusion

I am extremely confused about resource management in C++/CLI. I thought I had a handle (no pun intended) on it, but I stumbled across the auto_gcroot<T> class while looking through header files, which led to a google search, then the better part of day reading documentation, and now confusion. So I figured I'd turn to the community.
My questions concern the difference between auto_handle/stack semantics, and auto_gcroot/gcroot.
auto_handle: My understanding is that this will clean up a managed object created in a managed function. My confusion is that isn't the garbage collector supposed to do that for us? Wasn't that the whole point of managed code? To be more specific:
//Everything that follows is managed code
void WillThisLeak(void)
{
String ^str = gcnew String ^();
//Did I just leak memory? Or will GC clean this up? what if an exception is thrown?
}
void NotGoingToLeak(void)
{
String ^str = gcnew String^();
delete str;
//Guaranteed not to leak, but is this necessary?
}
void AlsoNotGoingToLeak(void)
{
auto_handle<String ^> str = gcnew String^();
//Also Guaranteed not to leak, but is this necessary?
}
void DidntEvenKnowICouldDoThisUntilToday(void)
{
String str();
//Also Guaranteed not to leak, but is this necessary?
}
Now this would make sense to me if it was a replacement for the C# using keyword, and it was only recommended for use with resource-intensive types like Bitmap, but this isnt mentioned anywhere in the docs so im afraid ive been leaking memory this whole time now
auto_gcroot
Can I pass it as an argument to a native function? What will happen on copy?
void function(void)
{
auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere
manipulateBmp(bmp);
pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot?
}
#pragma unmanaged
void maipulateBmp(auto_gcroot<Bitmap ^> bmp)
{
//Do stuff to bmp
//destructor for bmp is now called right? does this call dispose?
}
Would this have worked if I'd used a gcroot instead?
Furthermore, what is the advantage to having auto_handle and auto_gcroot? It seems like they do similar things.
I must be misunderstanding something for this to make so little sense, so a good explanation would be great. Also any guidance regarding the proper use of these types, places where I can go to learn this stuff, and any more good practices/places I can find them would be greatly appreciated.
thanks a lot,
Max
Remember delete called on managed object is akin to calling Dispose in C#. So you are right, that auto_handle lets you do what you would do with the using statement in C#. It ensures that delete gets called at the end of the scope. So, no, you're not leaking managed memory if you don't use auto_handle (the garbage collector takes care of that), you are just failing to call Dispose. there is no need for using auto_handle if the types your dealing with do not implement IDisposable.
gcroot is used when you want to hold on to a managed type inside a native class. You can't just declare a manged type directly in a native type using the hat ^ symbol. You must use a gcroot. This is a "garbage collected root". So, while the gcroot (a native object) lives, the garbage collector cannot collect this object. When the gcroot is destroyed, it lets go of the reference, and the garbage collector is free to collect the object (assuming it has no other references). You declare a free-standing gcroot in a method like you've done above--just use the hat ^ syntax whenever you can.
So when would you use auto_gcroot? It would be used when you need to hold on to a manged type inside a native class AND that managed type happens to implement IDisposable. On destruction of the auto_gcroot, it will do 2 things: call delete on the managed type (think of this as a Dispose call--no memory is freed) and free the reference (so the type can be garbage collected).
Hope it helps!
Some references:
http://msdn.microsoft.com/en-us/library/aa730837(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/481fa11f(v=vs.80).aspx
http://www.codeproject.com/Articles/14520/C-CLI-Library-classes-for-interop-scenarios

Pointers in and out of DLLs

Is it possible to pass a pointer to an object into a DLL, initialize it, and then use the initialized pointer in the main application? If so how? Are there any good articles on the subject, perhaps a tutorial?
I have read this article http://msdn.microsoft.com/en-us/library/ms235460.aspx But that did not seem to get me any where. Maybe I am misinterpreting it...
Yes, this is fine, but assuming your DLL has dynamically allocated the data being pointed to by the buffer, you must be careful about how you free it. There are a few ways to deal with this:
The DLL documents a method by which one should free the data (i.e., CoTaskFree)
The DLL exposes a function that should be called to later free the data
The DLL and the caller are using a common DLL-based runtime; this allows the caller to use the C++ delete operator
Yes.
Assuming you are using Microsoft Visual Studio as your development environment you can export a class rather directly from a dll. Add a define to your dll project something like BUILDING_THE_DLL and the following code snippit will export a c++ class wholesale from the dll.
#ifdef BUILDING_THE_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class EXPORT DllClass
{
....
};
This is a highly coupled solution and only works if you build the application and its dll using the same development environment, and rebuild both whenever the class definition changes in any way. this method is heavilly used by the MFC library.
To achieve a greater independence between the dll and app, one typically defines a relatively immutable interface and uses that to make builds more independent, and possibly use different build environments.
An implementation in your dll would look something like this:
struct IMyInterface {
virtual void Destroy() =0;
virtual void Method() = 0;
};
class MoDllObject : public IMyInterface
{
// implementation
};
bool EXPORT DllGetInterface(IMyInterface** ppOut)
{
*ppOut = new MyDllObject();
return true;
}

Resources