I am trying to write a C++/CLI wrapper using VS2010 against an C++ API for which I only have access to header files, and a dll/lib file.
I’m running into a problem with the bubbling back up of a native reference from the native code, to the tracking reference in the C# code. I get a SystemAccessViolation. The code is as follows:
Unmanaged Native C++ Headers for native Functions that returns a reference to Create the as well as to Modify the CustomObject:
class ManageCustomObject;
_declspec(dllimport) errorCode CreateCustomObject(CustomObject& customObject);
_declspec(dllimport) errorCode ModifyCustomObject(CustomObject& customObject);
Important thing to note about CustomObject is that it has private constructors only:
CustomObject(const CustomObject&) { }
CustomObject& operator=(const CustomObject&) { return *this; }
Now, my C++/CLI layer Method looks like this:
public ref class WrapperManageCustomObject {
public:
errorCode WrapperCreateCustomObject(CustomObject% customObject)
{
return CreateCustomObject(customObject);
}
errorCode WrapperModifyCustomObject(CustomObject% customObject)
{
return ModifyCustomObject(customObject);
}
};
And the wrapper for the CustomObject looks like this:
public class WrapperCustomObject : public CustomObject {
public:
WrapperCustomObject(const CustomObject&) {};
};
In C# the code goes as follows:
WrapperCustomObject wrapperCustomObject;
WrapperManageCustomObject wrapperManageCustomObject = new WrapperManageCustomObject();
long result;
// this works great
result = wrapperManageCustomObject.CreateCustomObject(ref wrapperCustomObject);
// can utilize wrapperCustomObject here with other native functions no problem, so long as I don't try to modify it...
...
// this throws an AccessViolationException was unhandled message
// essentially I am modifying / returning a different native customObject (though I'm not 100% sure what it does as I do not have access to the code)
result = wrapperManageCustomObject.ModifyCustomObject(ref wrapperCustomObject);
As you can see in my comments, the attempt to modify that object via reference throw an “AccessViolationException was unhandled : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.”
Now, if I eliminate C# and the tracking reference from this equation and do this all within C++ or C++/CLI (so long as the tracking reference is not present), this works fine. I assume this has something to do with native code trying to access updating a reference that is now in managed-land.
Is there any way around any of this to essentially make this code “work” from within C#? There is no way to pass a native reference to C# that I am aware of.
Managed references are absolutely nothing like native references. Managed references are more like native pointers. As far as I am aware, you can’t do somthing like
public class WrapperCustomObject : public CustomObject(whereCustomObjectis a native class) and ever expect that to work. When you create a managed class, you are telling the CLR that your class will be well behaved in the face of being moved around in memory. IfCustomObjectdoes anything with pointers at all, that’s no longer going to be true.CustomObjectdoes not use managed references, and therefore the runtime has no way of knowing where to update clients if/when that class instance gets moved around.Even worse, your wrapper is allowing that class to be instantiated without going through the factory method. Therefore, if the factory method
CreateCustomObjectdoes anything important to the object you get back, you’ve violated the contract of the code you’re calling, which asked you to create instances of that object through the factory method only.