.NET与Java通过Kernel32.dll实现内存共享

废话不多说,上代码
.Net代码

class Program
{
    static readonly string ShareMemoryName = nameof(ShareMemoryName);
    static readonly uint capacity = 1 << 10;
    static void Main(string[] args)
    {
        WriteShareMemory("Hello Word!!!", ShareMemoryName, capacity);
        string memoryContent = ReadShareMemory(ShareMemoryName, capacity);
        Console.WriteLine(memoryContent);

        WriteShareMemory("ReWrite Content!!!", ShareMemoryName, capacity);
        string memoryReWriteContent = ReadShareMemory(ShareMemoryName, capacity);
        Console.WriteLine(memoryReWriteContent);
    }

    public static void WriteShareMemory(string content, string shareName, uint capacity)
    {
        var shareMemory = new ShareMemoryHelper(shareName, capacity);
        shareMemory.CreateShareMemoryMap(shareName, capacity);
        byte[] buffer = Encoding.UTF8.GetBytes(content);
        byte[] writeBuffer = new byte[capacity];
        for (int i = 0; i < buffer.Length; i++)
        {
            writeBuffer[i] = buffer[i];
        }
        shareMemory.Write(writeBuffer, 0, writeBuffer.Length);
    }

    public static string ReadShareMemory(string shareName, uint capacity)
    {
        var shareMemory = new ShareMemoryHelper(shareName, capacity);
        shareMemory.GetShareMemoryMap(shareName, capacity);
        byte[] buffer = new byte[capacity];
        shareMemory.Read(ref buffer, 0, buffer.Length);
        return Encoding.UTF8.GetString(buffer);
    }
}

public class ShareMemoryHelper : IDisposable
{
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
    [DllImport("kernel32", EntryPoint = "GetLastError")]
    public static extern int GetLastError();
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);


    public IntPtr fileMapping = IntPtr.Zero;
    public IntPtr mapView = IntPtr.Zero;
    const int FILE_MAP_COPY = 0x0001;
    const int FILE_MAP_WRITE = 0x0002;
    const int FILE_MAP_READ = 0x0004;
    const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;
    const int PAGE_READWRITE = 0x04;
    const int INVALID_HANDLE_VALUE = -1;
    const int ERROR_ALREADY_EXISTS = 183;
    private bool bValid;
    bool m_bAlreadyExist = false;
    bool m_bInit = false;
    long m_MemSize = 0;
    public ShareMemoryHelper(string name, uint length)
    {
        bValid = GetShareMemoryMap(name, length);
    }
    public ShareMemoryHelper() { }

    ~ShareMemoryHelper()
    {
        Close();
    }
    public bool GetShareMemoryMap(string name, uint length)
    {
        m_MemSize = length;
        fileMapping = OpenFileMapping(PAGE_READWRITE, false, name);
        if (fileMapping == IntPtr.Zero)
        {
            return false;
        }
        mapView = MapViewOfFile(fileMapping, (uint)FILE_MAP_READ, 0, 0, length);
        if (mapView == IntPtr.Zero)
        {
            int a = GetLastError();
            return false;
        }
        m_bInit = true;
        return true;
    }

    public int CreateShareMemoryMap(string strName, long lngSize)
    {
        try
        {
            if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000;
            m_MemSize = lngSize;
            if (strName.Length > 0)
            {
                fileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName);
                if (fileMapping == IntPtr.Zero)
                {
                    return 2;
                }

                if (GetLastError() == ERROR_ALREADY_EXISTS)
                {
                    m_bAlreadyExist = true;
                }
                else
                {
                    m_bAlreadyExist = false;
                }
                mapView = MapViewOfFile(fileMapping, FILE_MAP_WRITE, 0, 0, (uint)lngSize);
                if (mapView == IntPtr.Zero)
                {
                    m_bInit = false;
                    CloseHandle(fileMapping);
                    return 3;
                }
                else
                {
                    m_bInit = true;
                    if (m_bAlreadyExist == false)
                    {
                    }
                }
            }
            else
            {
                return 1;
            }
            return 0;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public int Write(byte[] bytData, int lngAddr, int lngSize)
    {
        try
        {
            if (lngAddr + lngSize > m_MemSize) return 2;
            if (m_bInit)
            {
                Marshal.Copy(bytData, lngAddr, mapView, lngSize);
            }
            else
            {
                return 1;
            }
            return 0;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public int Read(ref byte[] bytData, int lngAddr, int lngSize)
    {
        try
        {
            if (lngAddr + lngSize > m_MemSize) return 2;
            if (m_bInit)
            {
                Marshal.Copy(mapView, bytData, lngAddr, lngSize);
            }
            else
            {
                return 1;
            }
            return 0;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public void Close()
    {
        try
        {
            if (m_bInit)
            {
                UnmapViewOfFile(mapView);
                CloseHandle(fileMapping);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public void Dispose()
    {
        try
        {
            Close();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}



Java代码

<properties>
  <jna.version>5.9.0</jna.version>
</properties>

<dependency>
  <groupId>net.java.dev.jna</groupId>
  <artifactId>jna-platform</artifactId>
  <version>${jna.version}</version>
</dependency>
import com.sun.jna.Native;
import com.sun.jna.win32.W32APIOptions;

public interface IShareMemory extends com.sun.jna.platform.win32.Kernel32 {
    IShareMemory Instance = Native.load("kernel32", IShareMemory.class, W32APIOptions.DEFAULT_OPTIONS);
    HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
}

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinNT;

public class ShareMemoryHelper {
    public WinNT.HANDLE fileMapping = null;
    public Pointer mapView = null;
    final int FILE_MAP_COPY = 0x0001;
    final int FILE_MAP_WRITE = 0x0002;
    final int FILE_MAP_READ = 0x0004;
    final int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;
    final int PAGE_READWRITE = 0x04;
    final WinNT.HANDLE INVALID_HANDLE_VALUE = new WinNT.HANDLE();
    final int ERROR_ALREADY_EXISTS = 183;
    private boolean bValid;
    boolean m_bAlreadyExist = false;
    boolean m_bInit = false;
    long m_MemSize = 0;

    public ShareMemoryHelper(String name, long length) {
        bValid = GetShareMemoryMap(name, length);
    }

    public ShareMemoryHelper() {
    }

    public boolean GetShareMemoryMap(String name, long length) {
        m_MemSize = length;
        fileMapping = IShareMemory.Instance.OpenFileMapping(PAGE_READWRITE, true, name);
        if (fileMapping == null) {
            return false;
        }
        mapView = IShareMemory.Instance.MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, (int) length);
        if (mapView == null) {
            int a = IShareMemory.Instance.GetLastError();
            return false;
        }
        m_bInit = true;
        return true;
    }

    public int CreateShareMemoryMap(String strName, long lngSize) {
        if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000;
        m_MemSize = lngSize;
        if (strName.length() > 0) {
            fileMapping = IShareMemory.Instance.CreateFileMapping(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, (int) lngSize, strName);
            if (fileMapping == null) {
                return 2;
            }

            if (IShareMemory.Instance.GetLastError() == ERROR_ALREADY_EXISTS) {
                m_bAlreadyExist = true;
            } else {
                m_bAlreadyExist = false;
            }
            mapView = IShareMemory.Instance.MapViewOfFile(fileMapping, FILE_MAP_WRITE, 0, 0, (int) lngSize);
            if (mapView == null) {
                m_bInit = false;
                IShareMemory.Instance.CloseHandle(fileMapping);
                return 3;
            } else {
                m_bInit = true;
                if (m_bAlreadyExist == false) {
                }
            }
        } else {
            return 1;
        }
        return 0;
    }

    public int Write(byte[] bytData, int lngAddr, int lngSize) {
        if (lngAddr + lngSize > m_MemSize) return 2;
        if (m_bInit) {
            mapView.write(0, bytData, lngAddr, lngSize);
        } else {
            return 1;
        }
        return 0;
    }

    public byte[] Read(int lngAddr, int lngSize) {
        if (lngAddr + lngSize > m_MemSize) return null;
        if (!m_bInit) return null;
        byte[] bytes = new byte[lngSize];
        mapView.read(0, bytes, lngAddr, lngSize);
        return bytes;
    }

    public void Close() {
        if (m_bInit) {
            IShareMemory.Instance.UnmapViewOfFile(mapView);
            IShareMemory.Instance.CloseHandle(fileMapping);
        }
    }
}

import xxx.xxx.ShareMemoryHelper;
import java.io.UnsupportedEncodingException;

public class App 
{
    static String ShareMemoryName = "ShareMemoryName";
    static int capacity = 1 << 10;

    public static void main( String[] args ) throws UnsupportedEncodingException {
        WriteShareMemory("ReWrite Content!!!", ShareMemoryName, capacity);
        String memoryReWriteContent = ReadShareMemory(ShareMemoryName, capacity);
        System.out.println(memoryReWriteContent);
        memoryReWriteContent = ReadShareMemory(ShareMemoryName, capacity);
        System.out.println(memoryReWriteContent);
    }
    public static void WriteShareMemory(String content, String shareName, int capacity) throws UnsupportedEncodingException {
        ShareMemoryHelper shareMemory = new ShareMemoryHelper(shareName, capacity);
        shareMemory.CreateShareMemoryMap(shareName, capacity);
        byte[] buffer = content.getBytes("utf-8");
        byte[] writeBuffer = new byte[capacity];
        for (int i = 0; i < buffer.length; i++)
        {
            writeBuffer[i] = buffer[i];
        }
        shareMemory.Write(writeBuffer, 0, writeBuffer.length);
    }

    public static String ReadShareMemory(String shareName, int capacity) throws UnsupportedEncodingException {
        ShareMemoryHelper shareMemory = new ShareMemoryHelper(shareName, capacity);
        shareMemory.GetShareMemoryMap(shareName, capacity);
        byte[] buffer = shareMemory.Read(0, capacity);
        return new String(buffer,"utf-8");
    }
}

参考资料:
记录:C#创建共享内存,可用于两个独立进程间的通信
JNA使用OpenFileMapping获取句柄

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值