Can a reference/managed class contain native/non-managed members?

I am trying to wrap up some native functions into a managed class wrapper.

Some of these native functions use a FILE* as one of its parameters. For example, I might have a function like:

void readWackyRecord(FILE *filePtr, char *buffer)

This function will read a record from a file pointed at by filePtr and return the record in the character buffer to the user.

I was thinking of enclosing this function into a managed class called FileUtilities like so:

public ref class FileUtilities
{
private:
FILE *m_fp;
String ^m_filename;

public:
FileUtilities(String ^filename);
void WReadWackyRecord(String ^%buffer);
}


To use the new function, you first must instantiate an object of class FileUtilities like so:

FileUtilities ^futil = gcnew FileUtilies("myWackyFile.txt");

Now you can read records from the file by the following:

futil->WReadWackyRecord(buffer);

But I'm running into problems implementing the constructor. My constructor looks like

FileUtilities(String ^f)
{
// Convert .NET String to char *
char *fn = (char *)Marshal::StringToHGlobalAnsi(f).ToPointer();

// Open file for reading
fopen_s(&m_filePtr, fn, "r");

// Free the unmanaged memory
Marshal::FreeHGlobal((IntPtr)fn);
}


The error I am getting is:

error C2664 'fopen_s' cannot convert parameter 1 from 'cli::interior_ptr<Type>' to FILE **'

I don't understand this error. I declared m_filePtr to be of type FILE* so why does it think it is of type cli::interior_ptr<Type> Shouldn't m_filePtr be an unmanaged FILE*






Answer this question

Can a reference/managed class contain native/non-managed members?

  • Hassan Ayoub

    The problem here stems from the fact that the garbage collector for the .NET runtime can move objects in memory. This means that if you take the address of a member of such an object and the object then moves the memory you have is not longer valid. To get around this issue the C++ compiler generates what is called an interior pointer whenever it needs to take the address of a member of an object that may move in memory. The .NET runtime knows about interior pointers and will up date them if the associated object moves.

    Of course, this doesn't solve your problem. I usually get around this issue by reverting to the old CS rule about adding another layer of indirection.

    FILE* pFile;

    fopen_s(&pFile, ...);

    m_filePtr = pFile;

    The avoids creating the interior pointer and the issue of passing it out to code that knows nothing about interior pointers.



  • Barzot

    Oh wow, now I understand what is going on. Thanks a lot for the help.



  • Can a reference/managed class contain native/non-managed members?