4

Suppose I have the following simple wrapper of a NativeClassInstance.

public ref class Wrapper
{
private:
    NativeClass *_wrapped;
public:
    Renderer()
    {
        _wrapped = new NativeClass();
    }
    ~Renderer()
    {
        delete _wrapped;
    }
    operator NativeClass*()
    {
        return _wrapped;
    }
}

Now, I want to create an instance of Wrapper from C# with Wrapper wrapper = new Wrapper() and use it in another native functionalities wrapper that resides in another assembly with Helper.Foo(wrapper) (nothing strange having other functionalities not directly related to the wrapped classes in another assembly, IMO):

// Utilities is in another Assembly
public ref class Helper
{
public:
    static Foo(Wrapper ^wrapper)
    {
        // Do something in native code with wrapper->_wrapped
    }
}

The results with the implicit user conversion is:

  • candidate function(s) not accessible

If I make _wrapped public it is:

  • cannot access private member declared in class ...

Now, I've learnt that native type visibility is private outside of the assembly. So, how I'm supposed to use the wrapped entity in native code outside the assembly it's defined? I've read of make_public but you can't use with template types so it seems very limiting in the general case. Am I missing something? Is there a more correct solution?

ceztko
  • 14,736
  • 5
  • 58
  • 73

2 Answers2

2

I haven't been able to successfully expose native types using make_public, however a solution I have used is to put NativeClass in its own native DLL and then a) reference the native DLL from both assemblies; and b) pass the pointer to the native class around as an IntPtr.

Under the above scenario, instead of having an operator NativeClass* you might use a property such as

property IntPtr WrappedObject {
    IntPtr get() { return IntPtr(_wrapped); }
}

You then retrieve NativeObject in you helper assembly by

static void Foo(Wrapper ^wrapper)
{
    NativeObject *_wrapped
        = static_cast<NativeObject*>(wrapper->WrappedObject.ToPointer());
    // ... do something ...
}
mcdave
  • 2,550
  • 17
  • 22
  • Yes, I've thought (and for sure read in other places) about this solution. Now that I see it in your answer it doesn't look that bad... – ceztko May 25 '11 at 04:34
1

If you use make_public, your solution of making _wrapped public should work (it would obviously be best to make a public accessor instead). Regarding your comment "I've read of make_public but you can't use with template types so it seems very limiting in the general case." I agree--read here for the workaround I used: http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/b43cca63-b0bf-451e-b8fe-74e9c618b8c4/

More related info: Best workaround for compiler error C2158: make_public does not support native template types

Good luck!

Community
  • 1
  • 1
Matt Smith
  • 17,026
  • 7
  • 53
  • 103
  • Lol, I had already seen your answer! I think for one time I should just accept this limitation and its workarounds. – ceztko May 25 '11 at 04:54
  • Actually, this is not a bad workaround. An explicit conversion operator on the native wrappER type (to the native wrappED type) may also help usability. – ceztko Jul 09 '11 at 03:49
  • Citing the solution on the msdn site. "So make a native class VectorOfNativeB and store a pointer/ref to a std::vector in it. Put this class in B and make it public by using the make_public pragma. Change GetMgdClassB method to take a pointer/ref to this native class", Mike Danes (Microsoft Community Contributor, Moderator). – ceztko Jul 09 '11 at 03:53