Java NativeCall库返回数据类型

时间:2012-09-03 01:19:00

标签: java dll jna

我目前正在尝试使用Java中的NTX索引访问DBF。我有很多年前Artemis引擎(现在的ApolloDB)的副本,它在VB6中可以做到这一点。它使用3个DLL,主要是SDE32.DLL。

我已经使用NativeCall成功访问了这些DLL中的许多函数

public static VoidCall sx_Zap = new VoidCall("SDE32", "sx_Zap"); public static IntCall sx_Use = new IntCall("SDE32", "sx_Use");

intFile = sx_Use.executeCall(fileName);
        if (intFile == 0){
            if (JOptionPane.showOptionDialog(null, "Could not open:" + fileName + "\nRetry?", "Failed to open DBF", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null) != JOptionPane.YES_OPTION){
                return;
            }else{
                sx_Zap.executeCall();
            }
        }

该代码将很乐意打开并删除数据库,因此我知道我在正确的轨道上。请注意,当我想返回一个整数时,我使用了IntCall,当我想要什么都不返回时,我使用了VoidCall。

我发现的问题是某些功能,例如某些数据访问功能会返回字符串,例如VB6中的函数声明,用于从当前记录获取字符串字段的sx_GetString函数。 Declare Function sx_GetString Lib "sde32.dll" (ByVal cpFieldName As String) As String

如何将此信息导入Java?似乎只有int(和boolean)和void返回类型,我怎样才能得到String,double和long类型?

使用JNA我可以访问双打并看起来很长,但是当我尝试字符串返回类型时,我得到了执行保护违规并且Java崩溃了。

JNA示例:

public interface SDE32 extends Library {
   public String sx_GetString(String cpFieldName);
   public Double sx_GetDouble(String cpFieldName);
   public Long sx_GetLong(String cpFieldName);

}

JNADBF.SDE32 sde = (JNADBF.SDE32) Native.loadLibrary("SDE32", JNADBF.SDE32.class);
    System.out.println(sde.sx_GetString("TILLNAME"));
    System.out.println(sde.sx_GetDouble("SELLPRICE"));

JNA错误:

Execution protection violation

#

# A fatal error has been detected by the Java Runtime Environment:

#

# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000, pid=11104, tid=11060

那么如何获得这些返回类型?特别是String。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我建议先返回一个Pointer(而不是String),然后使用各种Pointer方法检查它指向的内存。一旦了解了函数返回的内容,就可以弄清楚如何使JNA正确地(自动或显式)恢复数据。

修改

public interface SDE32 extends StdCallLibrary {
   public Pointer sx_GetString(String cpFieldName); // don't use String just yet
   public double sx_GetDouble(String cpFieldName);
   // Don't use Java "long" unless you want a 64-bit integer
   // On windows, native "int" and "long" are both 32 bits
   public NativeLong sx_GetLong(String cpFieldName);
}

修改 有关更新版本的pascal header files,您应该使用shortsmallInt的Java类型WordBoolint的{​​{1}} }。但是,切换到这些类型并不能提供完整的修复(它会减少堆栈损坏 - 您将使用错误的标志“打开”DB)。