简体   繁体   中英

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 populated 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

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.

The best practice for sharing memory would be to use the MemoryMappedFile class in C# and CreateFileMapping / MapViewOfFile in C++.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM