You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++与Java进程间通信:字符串数据传递实现入门问询

在Java和C++之间通过IPC传递字符串(管道/共享内存实现)

Hey, let's figure out how to get that C++ message string into your Java Recv class using IPC. I'll walk you through two practical approaches—named pipes (simple, no extra dependencies) and shared memory (faster, for high-throughput scenarios)—with code you can drop into your projects.


一、Named Pipes(命名管道)方案

Named pipes work across processes (and even across languages) because they act like a file-based communication channel. Perfect for straightforward string passing.

C++ 发送端代码

This creates the pipe and writes your message variable to it. It handles both Windows and Linux:

#include <iostream>
#include <fstream>
#include <string>
#ifdef _WIN32
#include <windows.h>
#define PIPE_NAME "\\\\.\\pipe\\JavaCppPipe"
#else
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#define PIPE_NAME "/tmp/JavaCppPipe"
#endif

int main() {
    std::string message = "Hello from C++!"; // Your target message variable

#ifdef _WIN32
    // Create named pipe on Windows
    HANDLE hPipe = CreateNamedPipe(
        PIPE_NAME,
        PIPE_ACCESS_OUTBOUND,
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        0,
        0,
        0,
        NULL
    );
    if (hPipe == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to create pipe!" << std::endl;
        return 1;
    }
    // Wait for Java to connect
    if (!ConnectNamedPipe(hPipe, NULL)) {
        std::cerr << "Failed to connect to pipe!" << std::endl;
        CloseHandle(hPipe);
        return 1;
    }
    // Write message to pipe (include null terminator)
    DWORD bytesWritten;
    BOOL success = WriteFile(
        hPipe,
        message.c_str(),
        message.size() + 1,
        &bytesWritten,
        NULL
    );
    if (!success) {
        std::cerr << "Failed to write to pipe!" << std::endl;
        CloseHandle(hPipe);
        return 1;
    }
    CloseHandle(hPipe);
#else
    // Create named pipe on Linux
    mkfifo(PIPE_NAME, 0666);
    int fd = open(PIPE_NAME, O_WRONLY);
    if (fd == -1) {
        std::cerr << "Failed to open pipe!" << std::endl;
        return 1;
    }
    // Write message
    write(fd, message.c_str(), message.size() + 1);
    close(fd);
    unlink(PIPE_NAME); // Clean up pipe after use
#endif
    return 0;
}

Java 接收端(修改你的Recv类)

This reads from the pipe and populates your Java message variable:

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;

public class Recv {
    public static String message; // Your target variable to populate

    public static void main(String[] args) {
        String pipeName;
        // Handle cross-platform pipe name differences
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            pipeName = "\\\\.\\pipe\\JavaCppPipe";
        } else {
            pipeName = "/tmp/JavaCppPipe";
        }

        try (RandomAccessFile pipe = new RandomAccessFile(pipeName, "r")) {
            byte[] buffer = new byte[1024];
            int bytesRead = pipe.read(buffer);
            if (bytesRead > 0) {
                // Convert bytes to string and trim any extra nulls
                message = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8).trim();
                System.out.println("Received from C++: " + message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Pro Tip: Run the Java program first (so it waits for the pipe connection), then start the C++ program to send the message.


二、Shared Memory(共享内存)方案

Shared memory is faster because it skips data copying between processes—both programs read/write directly to the same memory block. Java needs a little help here (we'll use JNA to call system APIs).

C++ 写入端代码

Creates a shared memory block and writes your message to it:

#include <iostream>
#include <string>
#ifdef _WIN32
#include <windows.h>
#define SHM_NAME "JavaCppSharedMem"
#else
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define SHM_KEY 12345
#define SHM_SIZE 1024
#endif

int main() {
    std::string message = "Hello from C++ Shared Memory!";

#ifdef _WIN32
    // Create shared memory on Windows
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        1024,
        SHM_NAME
    );
    if (hMapFile == NULL) {
        std::cerr << "Failed to create shared memory!" << std::endl;
        return 1;
    }
    char* pBuf = (char*)MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        1024
    );
    if (pBuf == NULL) {
        std::cerr << "Failed to map shared memory!" << std::endl;
        CloseHandle(hMapFile);
        return 1;
    }
    // Copy message to shared memory
    strcpy(pBuf, message.c_str());
    // Wait for Java to read (replace with semaphores in production)
    std::cout << "Data written to shared memory. Press Enter to exit..." << std::endl;
    std::cin.get();
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);
#else
    // Create shared memory on Linux
    int shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666);
    if (shmid == -1) {
        std::cerr << "Failed to get shared memory ID!" << std::endl;
        return 1;
    }
    char* pBuf = (char*)shmat(shmid, NULL, 0);
    if (pBuf == (char*)-1) {
        std::cerr << "Failed to attach to shared memory!" << std::endl;
        return 1;
    }
    // Copy message to shared memory
    strcpy(pBuf, message.c_str());
    // Wait for Java to read
    std::cout << "Data written. Press Enter to clean up..." << std::endl;
    std::cin.get();
    shmdt(pBuf);
    shmctl(shmid, IPC_RMID, NULL); // Clean up shared memory
#endif
    return 0;
}

Java 接收端(修改你的Recv类)

We'll use JNA (Java Native Access) to call system-level shared memory functions. First, add the JNA dependency if you're using Maven:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>

Then update your Recv class:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import java.nio.charset.StandardCharsets;

public class Recv {
    public static String message;

    // Interface for Linux C library functions
    interface CLibrary extends Library {
        CLibrary INSTANCE = Native.load("c", CLibrary.class);
        int shmget(int key, int size, int flag);
        Pointer shmat(int shmid, Pointer addr, int flag);
        int shmdt(Pointer shmaddr);
        int shmctl(int shmid, int cmd, Pointer buf);
    }

    public static void main(String[] args) {
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            // Read shared memory on Windows
            String shmName = "JavaCppSharedMem";
            WinNT.HANDLE hMapFile = Kernel32.INSTANCE.OpenFileMapping(
                Kernel32.FILE_MAP_ALL_ACCESS,
                false,
                shmName
            );
            if (hMapFile == null) {
                System.err.println("Failed to open shared memory!");
                return;
            }
            Pointer pBuf = Kernel32.INSTANCE.MapViewOfFile(
                hMapFile,
                Kernel32.FILE_MAP_ALL_ACCESS,
                0,
                0,
                1024
            );
            if (pBuf == null) {
                System.err.println("Failed to map shared memory!");
                Kernel32.INSTANCE.CloseHandle(hMapFile);
                return;
            }
            // Read string from shared memory
            message = pBuf.getString(0, StandardCharsets.UTF_8.name());
            System.out.println("Received from shared memory: " + message);
            Kernel32.INSTANCE.UnmapViewOfFile(pBuf);
            Kernel32.INSTANCE.CloseHandle(hMapFile);
        } else {
            // Read shared memory on Linux
            final int SHM_KEY = 12345;
            int shmid = CLibrary.INSTANCE.shmget(SHM_KEY, 1024, 0666);
            if (shmid == -1) {
                System.err.println("Failed to get shared memory ID!");
                return;
            }
            Pointer pBuf = CLibrary.INSTANCE.shmat(shmid, null, 0);
            if (pBuf == null) {
                System.err.println("Failed to attach to shared memory!");
                return;
            }
            message = pBuf.getString(0);
            System.out.println("Received from shared memory: " + message);
            CLibrary.INSTANCE.shmdt(pBuf);
        }
    }
}

Important: Shared memory doesn't have built-in synchronization. In production, use semaphores or mutexes to avoid race conditions (the example uses user input as a simple wait mechanism).


Quick Recommendation

  • Use named pipes if you want simplicity, no extra dependencies, and don't need maximum performance.
  • Use shared memory if you need fast, high-throughput communication (just remember to handle synchronization!).

内容的提问来源于stack exchange,提问作者Jas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:25:32