【问题标题】:Java Native Interface and Windows FormJava 本机接口和 Windows 窗体
【发布时间】:2013-11-15 15:46:41
【问题描述】:

所以,我有编译为 .dll 文件的 Visual Studio consloe 项目。 我创建了简单的窗口表单System::Windows::Forms::Form

我创建了一个 .java 文件:

 import java.io.Serializable;


public class MyBean implements Serializable{

    /**
     * 
     */
    static{
        System.loadLibrary("MyBean");
}
    private static final long serialVersionUID = 1L;


    private static native String getDateCpp();


    public String getDate(){
        return getDateCpp();
    }



}

编译它并通过javah生成一个.h文件:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyBean */

#ifndef _Included_MyBean
#define _Included_MyBean
#ifdef __cplusplus
extern "C" {
#endif
#undef MyBean_serialVersionUID
#define MyBean_serialVersionUID 1i64
/*
 * Class:     MyBean
 * Method:    getDateCpp
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_MyBean_getDateCpp
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

并实现了一个显示表单的 .cpp 文件:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "Form1.h"
#include "MyBean.h"
#include <string>
#include <vcclr.h>
using namespace std;


bool To_string( String^ source, string &target )
{
    pin_ptr<const wchar_t> wch = PtrToStringChars( source );
    int len = (( source->Length+1) * 2);
    char *ch = new char[ len ];
    bool result = wcstombs( ch, wch, len ) != -1;
    target = ch;
    delete ch;
    return result;
}

JNIEXPORT jstring JNICALL Java_MyBean_getDateCpp
    (JNIEnv * env, jclass jcl){
        Form1^ form = gcnew Form1();
        form->Show();

        String^ text = form->text;
        string stdString = "";


        if(To_string(text,stdString))
            return  (*env).NewStringUTF(stdString.c_str());
        else
            return (*env).NewStringUTF("blad");
}

编译成功后,我在尝试调用 c++ 函数后收到 java 错误:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000007f9324f811c, pid=4404, tid=4800
#
# JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.45-b08 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [KERNELBASE.dll+0x3811c]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\studia\semestr 7\java\lab05\hs_err_pid4404.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

而且日志很长,这里就不贴了。

我做错了什么?

【问题讨论】:

  • 不确定您的代码有什么问题,但它可能会简单得多。在 Windows 上,Java 使用代码单元计数、UTF-16LE 编码的 Unicode 字符串。 .NET 使用代码单元计数、UTF-16LE 编码的 Unicode 字符串....幸福。因此,获取 .NET 字符串的“长度”,用PtrToStringChars 固定它并将该信息传递给env-&gt;NewString;取消固定,你就完成了。 (NewStringUTF 和 GetStringCharsUTF 使用 modified UTF_8 编码,这是非 Unicode 函数的拐杖。)
  • 谢谢,您的评论很有价值,但它有效,正如我在下面提到的答案,问题出在show(),我应该使用showDialog()
  • “它有效,”真的吗?将“You win a trip to Bangkok and ฿150,000”粘贴到您的文本框中,看看会发生什么。

标签: java c++ winforms java-native-interface


【解决方案1】:

呃……

  1. wcstombs 永远不会返回小于 0 的值。请参见此处:http://www.cplusplus.com/reference/cstdlib/wcstombs/

  2. 这是标记为 c++,所以我认为您应该使用 env-&gt; 而不是 (*env).。没什么大不了的,但嗯..

  3. 我不确定您是否需要它,但我认为您在 JNI 函数之前缺少extern "C"

最后,确保您的调用约定是正确的。不久前我遇到了同样的问题/异常/转储:Loading JNI Dll

我通过更改调用约定并使用 .def 文件导出解决了这个问题。我相信您需要解决的只是调用约定。不需要 .def 文件;只是想我还是会提到它。

每当您收到该错误时,都是由于调用约定问题。很少是由于权限,但这也是值得关注的。也许您可能需要以管理员身份运行。

【讨论】:

  • 好的,我会看看你的建议。我的 .h 文件中有 extern "C",我也应该在 .cpp 文件中添加它吗?
  • 错误很简单。我应该使用showDialog() 而不是show(),现在可以了,感谢提示和帮助。
【解决方案2】:

我打电话给form-&gt;Show();有一个错误,但我应该打电话给form-&gt;ShowDialog();

来自 MSDN:

显示对话框()

您可以使用此方法在您的 应用。调用此方法时,它后面的代码不是 直到对话框关闭后才执行。

显示()

显示控件相当于设置Visible 属性为真。调用 Show 方法后,Visible 在调用 Hide 方法之前,属性返回 true 值。

所以,当我调用 show 时,我得到了要转换的空字符串,而我的窗口只显示了一秒钟或更短的时间,现在它是模态的,它等待关闭,然后执行其余代码。 JNI 已正确实施并且工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多