.netdllc++-clifriendmixed-mode

friend ref class?


I have a managed class Parser and an unmanaged class CParser. The former is exposed from a DLL for managed clients (C# world). The core functionality is in the unmanaged class CParser. Since both are in the same DLL, and there is a one-to-one relationship, the managed class can access the unmanaged class.

The problem is that I want Parser to access all members of CParser. I don't want to use public: for all members, nor I am willing to have setters and getters. Thus, I just placed friend keyword:

class CParser
{
   ...
   friend ref class Parser; // C2144
};

// public ref class Parser{}; 

I get error C2144, probably for obvious reason that unmanaged C++ doesn't understand ref keyword. If I remove ref keyword, the managed compiler (compiling Parser), would complain with error C2872: Ambigious Symbol.

It is also known that internal: is not applicable for unmanged C++.

How to make Parser a friend of CParser ?

EDIT: This question was already here, but probably the unmanaged class is compiled under /clr. I cannot/will not compile unmanaged class using managed compiler.


Solution

  • You can't use friend in that case. The only way I have found to accomplish it is to declare another friend which gives free access to the private members, but is defined within the source file of the other class and thus cannot be used by any other code.

    This is ugly in its own way but at least the ugliness is hidden in the cpp file, and the public interface of the native class remains relatively clean.

    NativeClass.h

    class NativeClass
    {
    public:
            void PublicStuff();
            struct DispatchHelper;
    protected:
            friend DispatchHelper;
            void NonPublicStuff();
    };
    

    RefClass.h

    ref class RefClass
    {
    public:
        void ManagedCode();
    };
    

    RefClass.cpp

    struct NativeClass::DispatchHelper
    {
        static void DoStuff(NativeClass* p) { p->NonPublicStuff(); }
    }
    
    void RefClass::ManagedCode()
    {
        NativeClass::DispatchHelper::DoStuff(pNativeClass);
    }