【问题标题】:Empty String when sending a String value using WM_COPYDATA in JNA在 JNA 中使用 WM_COPYDATA 发送字符串值时为空字符串
【发布时间】:2021-10-18 00:12:20
【问题描述】:

我正在尝试将字符串从 Java(第一个应用程序)发送到 c++(第二个带有仅消息窗口的应用程序)。

首先,我尝试的是: 我将this example 改编到我的代码中,并在 java 端得到了这个

    STRMSG msg = new STRMSG();
    msg.message = "test";
    //msg.write(); // Idk exactly why because i thought JNA does this before every call. Works the same without

    cds = new COPYDATASTRUCT();
    cds.dwData = new ULONG_PTR(UniqueWindowMessageID);
    cds.cbData = msg.size();
    cds.lpData = msg.getPointer();
    cds.write(); // But here it is somehow needed because otherwise the message will not arrive.

    JNA.USER32.INSTANCE.SendMessage(
        msgOnlyWnd, WinUser.WM_COPYDATA,
        null,
        new LPARAM(Pointer.nativeValue(cds.getPointer()))
    );

哦,STRMSG 看起来像这样(也改编自示例):

public class STRMSG extends Structure {

    public STRMSG() {
        super();
    }

    public STRMSG(Pointer p) {
        super(p);
        read();
    }

    public String message;

    protected List<String> getFieldOrder() {
        return Arrays.asList("message");
    }
}

在 c++ 端,我得到了仅消息窗口,并且可以成功捕获 WM_COPYDATA 消息。

但不知何故,我的 String 值在这里是空的:

    case WM_COPYDATA: {
        PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam;
        if (cds->dwData == UniqueWindowMessageID) { // <- works 
            STRMSG* msgStruct = (STRMSG*)cds->lpData; // <- The message struct is corrupt i guess

            cout << msgStruct->message << endl; // Will just endl in the console
        }
        break;
    }

这是c++端的结构:

const struct STRMSG {
    string message;
};

除了这个尝试之外,我还尝试调整我的结构,使其包含一个 BYTE* (byte[]) 和大小,以便我可以使用以下字节和大小创建一个字符串:(source)

std::string s(reinterpret_cast<char const*>(inputParam), lengthParam);

但是我的结构无论如何都不是它应该的样子。所以数据在某种程度上是错误的,并且 IDK 我在这里做错了什么。

感谢任何帮助。

编辑:我还在调试时查看了数据。我什么都没得到:

EDIT2:

Remy 评论后,我的 COPYDATASTRUCT 看起来像这样:

    byte[] msg = "test".getBytes();
    cds = new COPYDATASTRUCT();
    cds.dwData = new ULONG_PTR(UniqueWindowMessageID);
    cds.cbData = msg.length;
    cds.lpData = msg // how??
    cds.write();

但是我应该如何将cds.lpData 映射到byte[]

【问题讨论】:

  • 我们已经在您的previous question 中介绍了这一点。您的 Java 代码犯了与您的 C++ 代码相同的错误。您只发送STRMSG 结构,而不是它指向的字符串数据。现在您正在使问题复杂化,因为 Java 代码正在发送 Java 的 string 类型,它与 C++ 的 std::string 类型不兼容。完全没有理由在这段代码中使用 STRMSG 结构,所以去掉它。让 Java 代码将 string 编码为 byte[] 数组,然后 WM_COPYDATA 可以将这些字节发送到 C++
  • 天哪……你说得对。会尝试。我被 JNA 的例子蒙蔽了双眼。
  • @RemyLebeau 好的,基本上在完全删除结构之后。如何将cds.lpData(即Pointer)映射到byte[]? (我也更新了问题)
  • 关于您的评论问题:当将结构作为参数传递给本机方法时,JNA 会自动编写结构。但你永远不会通过那个。因此,您正在为 STRMSG 分配本机内存并获取指向它的指针,但从不将您的 String 写入它。无论如何,您都会丢失分配,因此即使写入也无法正常工作。

标签: java c++ winapi jna sendmessage


【解决方案1】:

好的,基本上,在Remy Lebeau 的帮助下(一如既往),我设法将NativeString Class 包含在我的项目中,这使我可以获取PointerPointer 并使用直接在我的COPYDATASTRUCT.

我不得不在我自己的NativeStringClassinline 一些方法内容,因为其中一些也不可见。

无论如何,这是我用来构建COPYDATASTRUCT 的 sn-p,发送部分没有改变。

NativeString ns = new NativeString("Hello String", true); //true so its a wide string
cds = new COPYDATASTRUCT();
cds.dwData = new ULONG_PTR(UniqueWindowMessageID);
cds.cbData = ns.length()*2; //Without *2 the text will be only the half
cds.lpData = ns.getPointer();
cds.write();

这就是我在 C++ 端处理接收到的 WM_COPYDATA 消息的方式:

case WM_COPYDATA: {
    PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam;
    if (cds->dwData == UniqueWindowMessageID) {
        wchar_t* msg = (wchar_t*)cds->lpData;
        wcout << msg << endl;
    }
    break;
}

再次感谢@Remy Lebeau

【讨论】:

    猜你喜欢
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2020-12-02
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    相关资源
    最近更新 更多