我目前正在尝试使用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

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

非常感激任何的帮助。

最佳答案

我建议先返回一个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类型WordBool,对于int,应使用Long。但是,切换到这些类型并不能提供完整的解决方案(它将减少堆栈损坏-您将使用错误的标志“打开”数据库)。

10-04 23:23
查看更多