Best practice to share a struct from a C# program to a C++ win32 DLL?
What is the best practice to share memory of a struct from a C# program to a C++ win32 DLL?
I've used structs in managed shared memory using Boost between two C++ programs and it worked great. I'm lost on the best way to accomplish this between where the struct gets po开发者_StackOverflow中文版pulated in the C# program and the C++ DLL that is an SNMP subagent.
Here's the C++ DLL:
//==================== Code Excerpt from the main cpp file ======================
#include "stdafx.h"
//================= Here we are setting up the shared memory area =====================
#pragma data_seg (".SHAREDMEMORY")
struct sharedData {
int sharedA;
int sharedB;
};
static sharedData A;
#pragma data_seg()
#pragma comment(linker,"/SECTION:.SHAREDMEMORY,RWS")
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
return TRUE;
}
//=============================================================================================
//====================== Here we are writing wrappers to the shared memory area ===========================
//=You must declare it as an Extern "C" to prevent name mangling. This is absolutely necessary in order to import it into c# =
//=============================================================================================
extern "C" __declspec(dllexport) sharedData __stdcall getMyData()
{
A.sharedA = 1237;
A.sharedB = 31337;
//return gshared_nTest;
return A;
}
extern "C" __declspec(dllexport) void __stdcall setMyData( sharedData buff )
{
A = buff;
}
Here's the calling C# function:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace sharedMemTestCS
{
public partial class frmSharedMemTestCS : Form
{
struct sharedData {
int sharedA;
int sharedB;
};
static sharedData A;
//============== here we are importing the methods from the win32 dll into the c# console application =================
[DllImport(@"C:\Documents and Settings\My Documents\Visual Studio 2010\Projects\sharedMemTestCPP\Debug\sharedMemTestCPP.dll")]
public static extern sharedData getMyData();
[DllImport(@"C:\Documents and Settings\My Documents\Visual Studio 2010\Projects\sharedMemTestCPP\Debug\sharedMemTestCPP.dll")]
public static extern void setMyData(int data);
public frmSharedMemTestCS()
{
InitializeComponent();
//============== here i am incrementing the value =================
//== i use a message box so that i can have multiple console applications running at once and it will pause at the messagebox (if i don't click ok)
//== i do this so i can see the values changing in the shared memory.
//MessageBox.Show( getMyData().ToString() );
getMyData();
//txtBoxA.Text = (getMyData().ToString() );
}
private void btnAdd_Click(object sender, EventArgs e)
{
//setMyData( getMyData() + 100 );
//txtBoxA.Text = (getMyData().ToString() );
}
}
}
The error message I get is:
Error 1 Inconsistent accessibility: return type
'sharedMemTestCS.frmSharedMemTestCS.sharedData' is less accessible than method 'sharedMemTestCS.frmSharedMemTestCS.getMyData()' c:\documents and settings\mconrad\my documents\visual studio 2010\Projects\sharedMemTestCS\sharedMemTestCS\Form1.cs 23 37 sharedMemTestCS
The best practice for sharing memory would be to use the MemoryMappedFile
class in C# and CreateFileMapping
/MapViewOfFile
in C++.
First thing, you cannot straightway use Boost for data sharing. You need to have some well-defined data-structures that you share between the managed and unmanaged worlds.
You may start here
Well your actual problem is your p/invoke expression is public but your struct is private, which is what the error is telling you. Making your p/invoke expression private or your struct public will resolve the immediate issue.
As for the actual data sharing, I've never tried doing it quite like that so I can't tell you if it will or won't work. All the pieces I've worked with are marshalled back and forth. Looking at your example code, it's quite possible it could work. You'll probably want to either copy the data to a new struct for c# or pin your struct that you get back so the GC won't move it around in memory.
精彩评论