Reputation: 14011
I'm currently stuck trying to wrap a section of a native C++ API that uses a native C++ interface defined like this:
#pragma once
class BufferReaderInterface
{
public:
virtual ~BufferReaderInterface()
{
}
const static int BUFFER_SIZE = 100;
virtual void ReadNextBuffer(char* buffer) = 0;
};
It is then used by a parser class for reading data into it's local buffer for later parsing like this:
#pragma once
#include "BufferReaderInterface.h"
class BufferParser
{
public:
void ReadNextBuffer(BufferReaderInterface& reader)
{
reader.ReadNextBuffer(localBuffer);
}
void ParseBuffer()
{
// do buffer parsing after ReadNextBuffer()...
}
private:
char localBuffer[BufferReaderInterface::BUFFER_SIZE];
};
Here is a sample implementation for reading buffers from a file stream (it doesn't have to be a file stream it could also be implemented to read from the network as well):
#pragma once
#include <fstream>
#include "BufferReaderInterface.h"
class FileStreamBufferReader : public BufferReaderInterface
{
public:
FileStreamBufferReader(std::string filename)
{
bufferFile.open(filename.c_str(),
std::ios_base::in | std::ios_base::binary);
if(!bufferFile)
{
throw std::invalid_argument(filename);
}
}
~FileStreamBufferReader()
{
bufferFile.close();
}
void ReadNextBuffer(char* buffer)
{
bufferFile.read((char *)buffer, BUFFER_SIZE);
}
private:
std::ifstream bufferFile;
};
A simple usage would be as follows:
BufferReaderInterface* br = new FileStreamBufferReader("test.binary");
BufferParser parser;
parser.ReadNextBuffer(*br);
parser.ParseBuffer();
// use parsed data...
delete br;
How should I wrap the BufferParser
class? I am trying to use the Pimpl-idiom on it, but I'm stuck when it comes to properly implementing the managed version of ReadNextBuffer(BufferReaderInterface&)
function. I have tried creating a public interface class ManagedBufferReaderInterface
, but then I'm stuck because the BufferParser
takes a native C++ interface, and a C++/CLI class can't implement a native C++ interface like BufferReaderInterface
. Has anyone encountered this before?
Any advice would be appreciated!
Upvotes: 0
Views: 1355
Reputation: 4863
How about using an abstract class instead of an interface?
public ref class ManagedBufferReaderInterface abstract
{
private public: // internal
BufferReaderInterface * native_interface;
public:
ManagedBufferReaderInterface(BufferReaderInterface * nativeinterface)
: native_interface(nativeinterface)
{ ... }
//...
};
public ref class ManagedBufferParser
{
BufferParser * parser;
public:
ManagedBufferParser()
: parser(new BufferParser())
{ ... }
void ReadNextBuffer(ManagedBufferReaderInterface ^ reader)
{
parser->ReadNextBuffer(reader->native_interface);
}
void ParseBuffer()
{
parser->ParseBuffer();
}
//...
};
Added code:
#include <msclr\marshal_cppstd.h>
public ref class ManagedFileStreamBufferReader : public ManagedBufferReaderInterface
{
public:
ManagedFileStreamBufferReader(System::String ^ filename)
: ManagedBufferReaderInterface(new FileStreamBufferReader( msclr::interop::marshal_as<std::string>(filename) ) )
{ ... }
// ....
};
//Example
ManagedBufferReaderInterface ^ br = gcnew ManagedFileStreamBufferReader("test.binary");
ManagedBufferParser ^ parser = gcnew ManagedBufferParser();
parser->ReadNextBuffer(br);
parser->ParseBuffer();
Upvotes: 1