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*

Can a reference/managed class contain native/non-managed members?
killfr0g
OctopusThu
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.