I have code in C++
that I want to package as a dll and use in C#
code. I made the dll, but when I am loading it, I am getting System.AccessViolationException
. (First, the dll wouldn't load and after it has started loading, Access Violation has started to appear).
I wrote a piece of code in C++
that other members of my team want to incorporate into a windows forms application, I saw this as an opportunity to learn about C++
dll projects and incorporating them into C#/Windows Forms. I followed a tutorial on youtube and came up with this code for my dll:
extern "C" _declspec(dllexport) Communication* CreateCommunicationObject(const char* ip, unsigned int p_out, unsigned int p_in)
{
return &Communication::Communication(ip, p_out, p_in);
}
extern "C" _declspec(dllexport) st_rtioout getReceivedData(Communication *comm)
{
return comm->getData();
}
extern "C" _declspec(dllexport) void sendNewData(Communication *comm, st_rtioin *data)
{
return comm->sendData(*data);
}
extern "C" _declspec(dllexport) char* getReceptionStatus(Communication *comm)
{
return comm->getReceptionStatus();
}
extern "C" _declspec(dllexport) char* getSendingStatus(Communication *comm)
{
return comm->getSendingStatus();
}
The dll file was built and then I came into C#, I tried importing the dll as a reference in the Forms application but got an error "a reference to project2.dll could not be added. please make sure that the file is accessible and is a valid assembly or com component", after searching for a while, I came across this question. I then tried this in the C# application:
[DllImport("Project2.dll", EntryPoint = "CreateCommunicationObject", CallingConvention = CallingConvention.StdCall)]
static extern IntPtr CreateCommunicationObject(string ip, int port_out, int port_in);
[DllImport("Project2.dll", EntryPoint = "getReceivedData", CallingConvention = CallingConvention.StdCall)]
static extern st_rtioout getReceivedData(IntPtr ptr);
[DllImport("Project2.dll", EntryPoint = "sendNewData", CallingConvention = CallingConvention.StdCall)]
static extern void sendNewData(IntPtr ptr, st_rtioin sendingdata);
[DllImport("Project2.dll", EntryPoint = "getReceptionStatus", CallingConvention = CallingConvention.StdCall)]
static extern string getReceptionStatus(IntPtr ptr);
[DllImport("Project2.dll", EntryPoint = "getSendingStatus", CallingConvention = CallingConvention.StdCall)]
static extern string getSendingStatus(IntPtr ptr);
But now I am getting an error 'System.AccessViolationException'(Attempted to read or write protected memory. This is often an indication that other memory is corrupt.)
where I am calling the constructor of the class (createCommunicationObject
).
What am I doing wrong and how can I rectify it? thanks in advance. (I am using VS2013)
Edit:
After going through the comments and the answers, I tried all that you people suggested, but am still getting the same error. The New C++
code is:
extern "C" _declspec(dllexport) void Initialize(std::string ip, unsigned int p_out, unsigned int p_in)
{
const char* ipaddress = ip.c_str();
Communication comms = Communication(ipaddress, p_out, p_in);
Comms = &comms;
}
extern "C" _declspec(dllexport) st_rtioout getReceivedData()
{
return Comms->getData();
}
extern "C" _declspec(dllexport) void sendNewData(st_rtioin data)
{
Comms->sendData(data);
}
extern "C" _declspec(dllexport) std::string getReceptionStatus()
{
std::string str = Comms->getReceptionStatus();
return str;
}
extern "C" _declspec(dllexport) std::string getSendingStatus()
{
std::string str = Comms->getSendingStatus();
return str;
}
and the new C#
code is:
[DllImport("Project2.dll", EntryPoint = "Initialize", CallingConvention = CallingConvention.Cdecl)]
static extern void Initialize(string ip, int port_out, int port_in);
[DllImport("Project2.dll", EntryPoint = "getReceivedData", CallingConvention = CallingConvention.Cdecl)]
static extern st_rtioout getReceivedData();
[DllImport("Project2.dll", EntryPoint = "sendNewData", CallingConvention = CallingConvention.Cdecl)]
static extern void sendNewData(st_rtioin sendingdata);
[DllImport("Project2.dll", EntryPoint = "getReceptionStatus", CallingConvention = CallingConvention.Cdecl)]
static extern string getReceptionStatus();
[DllImport("Project2.dll", EntryPoint = "getSendingStatus", CallingConvention = CallingConvention.Cdecl)]
static extern string getSendingStatus();