在Windows操作系统中,Python与Win32之间的IPC通信问题

6
我有两个可以通过win32 IPC APIs(CreateFileMapping()等)进行通信的C应用程序。
我需要用Python应用程序替换客户端应用程序。
我已经在Python侧尝试了以下库:
import win32file, win32api
但是这些库没有CreateFileMapping()函数。
我还尝试了mmap.mmap()函数,但我无法观察到任何通信。
import mmap

sharedMemory = mmap.mmap(0, 512, "Local\\SharedBuffer")

sharedMemory.write("AB")

我也尝试过在双方都使用"Global\SharedBuffer"和"SharedBuffer"作为共享内存名称。
#define SHARED_BUFFER_NAME          ((LPCSTR)L"Local\\SharedBuffer")

HANDLE bufferHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 512, SHARED_BUFFER_NAME);

// Create a map for accessing Shared Buffer
sharedBuffer = (char*)MapViewOfFile(bufferHandle, FILE_MAP_ALL_ACCESS, 0, 0, SHARED_BUFFER_SIZE);

memset(sharedBuffer, 0, SHARED_BUFFER_SIZE);

while (sharedBuffer[0] == 0);

while (1);

对我来说,win32 API 不是必需的。在 Windows 平台上,我只需要一个简单的 C 和 Python 应用程序之间的共享缓冲区。

谢谢。


2
你为什么要将 const wchar_t* 强制转换为 const char* - Brandon
这个转换在哪里?MapViewOfFile()函数返回'void*',所以我将其转换为char数组以访问字节。 - muratcakmak
我仍然需要帮助。有任何回应吗? - muratcakmak
1
你在这里进行了类型转换:#define SHARED_BUFFER_NAME ((LPCSTR)L"Local\\SharedBuffer") 它应该是 LPCWSTR,但你将它强制转换为了 const char*,也就是 LPCSTR - Brandon
1
此外,您确定Python的mmap可以与Windows内存映射对象一起使用吗?它似乎与Java(内存映射文件)类似,这意味着您可以将磁盘上的文件进行内存映射,而不是页面。但我不确定这是否正确。您需要进行测试。 - Brandon
1
@Brandon:Windows使用内存映射的“文件区段”来实现共享内存。 - Ben Voigt
1个回答

16

我测试过了,它可行。首先运行C++代码,它将创建一个内存映射。然后运行Python代码,它将写入到内存映射中。C++代码将读取该映射并打印出所写入的内容。

我知道这段代码很糟糕,因为我没有正确地序列化数据(例如,首先将大小写入文件,然后再写入数据等等)。但是,这只是一个基本的工作示例,不要期望更多。

Python:

import mmap

shm = mmap.mmap(0, 512, "Local\\Test") #You should "open" the memory map file instead of attempting to create it..
if shm:
    shm.write(bytes("5", 'UTF-8'));
    shm.write(bytes("Hello", 'UTF-8'))
    print("GOOD")

C++:

#include <windows.h>
#include <cstring>
#include <cstdbool>
#include <iostream>

typedef struct
{
    void* hFileMap;
    void* pData;
    char MapName[256];
    size_t Size;
} SharedMemory;

bool CreateMemoryMap(SharedMemory* shm)
{
    if ((shm->hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, shm->Size, shm->MapName)) == NULL)
    {
        return false;
    }

    if ((shm->pData = MapViewOfFile(shm->hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, shm->Size)) == NULL)
    {
        CloseHandle(shm->hFileMap);
        return false;
    }
    return true;
}

bool FreeMemoryMap(SharedMemory* shm)
{
    if (shm && shm->hFileMap)
    {
        if (shm->pData)
        {
            UnmapViewOfFile(shm->pData);
        }

        if (shm->hFileMap)
        {
            CloseHandle(shm->hFileMap);
        }
        return true;
    }
    return false;
}

int main()
{
    SharedMemory shm = {0};
    shm.Size = 512;
    sprintf(shm.MapName, "Local\\Test");

    if (CreateMemoryMap(&shm))
    {
        char* ptr = (char*)shm.pData;
        memset(ptr, 0, shm.Size);

        while (ptr && (*ptr == 0))
        {
            Sleep(100);
        }

        int size = (int)*ptr;
        ptr += sizeof(char);

        int i = 0;
        for (; i < size; ++i)
        {
            std::cout<<ptr[i];
        }
        FreeMemoryMap(&shm);
    }
}

2
顺便说一下,这是C代码,不是真正的C++(除了使用std::cout之外)。我从我的Github中获取了这个C结构及其相关函数。 - Brandon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接