Mic*_*ber 90 java java-native-interface native-methods default-package
我正在使用Eclipse 3.5,我创建了一个包含一些包结构和默认包的项目.我在默认包中有一个类 - Calculations.java,我想在任何一个包中使用该类(例如in com.company.calc
).当我尝试使用默认包中的类时,它给了我一个编译器错误.它无法识别默认包中的类.问题出在哪儿?
Calculations.java - 源代码
public class Calculations {
native public int Calculate(int contextId);
native public double GetProgress(int contextId);
static {
System.loadLibrary("Calc");
}
}
Run Code Online (Sandbox Code Playgroud)
我不能把我的班级放在任何其他包中.这个类有一些在Delphi中实现的本机方法.如果我将该类放在任何文件夹中,我将不得不对我想要避免的DLL进行更改(实际上 - 我不能).这就是为什么我把我的类放在默认包中.
您的问题有一个解决方法.您可以使用反射来实现它.
首先,为目标类创建一个接口Calculatons
:
package mypackage;
public interface CalculationsInterface {
int Calculate(int contextId);
double GetProgress(int contextId);
}
Run Code Online (Sandbox Code Playgroud)
接下来,让目标类实现该接口:
public class Calculations implements mypackage.CalculationsInterface {
@Override
native public int Calculate(int contextId);
@Override
native public double GetProgress(int contextId);
static {
System.loadLibrary("Calc");
}
}
Run Code Online (Sandbox Code Playgroud)
最后,使用反射创建Calculations
类的实例并将其分配给类型的变量CalculationsInterface
:
Class<?> calcClass = Class.forName("Calculations");
CalculationsInterface api = (CalculationsInterface)calcClass.newInstance();
// Use it
double res = api.GetProgress(10);
Run Code Online (Sandbox Code Playgroud)
小智 5
我可以给你这个建议,据我的 C 和 C++ 编程经验,有一次,当我遇到同样的问题时,我通过更改“.C”文件中的 dll 写入结构通过更改名称来解决它实现 JNI 本机功能的函数。例如,如果您想将您的程序添加到包“com.mypackage”中,您将实现“.C”文件的函数/方法的JNI的原型更改为:
JNIEXPORT jint JNICALL
Java_com_mypackage_Calculations_Calculate(JNIEnv *env, jobject obj, jint contextId)
{
//code goes here
}
JNIEXPORT jdouble JNICALL
Java_com_mypackage_Calculations_GetProgress(JNIEnv *env, jobject obj, jint contextId)
{
//code goes here
}
Run Code Online (Sandbox Code Playgroud)
由于我是 Delphi 的新手,我不能向你保证,但最后会说,(我在谷歌搜索 Delphi 和 JNI 后学到了一些东西):问问那些提供原生 Delphi 实现的人(如果你不是那个人)将函数名称更改为以下内容的代码:
function Java_com_mypackage_Calculations_Calculate(PEnv: PJNIEnv; Obj: JObject; contextId: JInt):JInt; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
var
//Any variables you might be interested in
begin
//Some code goes here
end;
function Java_com_mypackage_Calculations_GetProgress(PEnv: PJNIEnv; Obj: JObject; contextId: JInt):JDouble; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
var
//Any variables you might be interested in
begin
//Some code goes here
end;
Run Code Online (Sandbox Code Playgroud)
但是,最后一个建议:虽然你(如果你是delphi程序员)或者他们会改变这些函数的原型并重新编译dll文件,但是一旦dll文件被编译,你将无法更改你的包名“Java”文件一次又一次。因为,这将再次要求您或他们使用更改的前缀(例如 JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)更改 delphi 中函数的原型
我认为这可以解决问题。谢谢和问候,哈沙尔·马尔什
从我在下面找到的一些地方:-
事实上,你可以。
到目前为止,您可以使用反射 API 访问任何类。至少我能够:)
Class fooClass = Class.forName("FooBar");
Method fooMethod =
fooClass.getMethod("fooMethod", new Class[] { String.class });
String fooReturned =
(String) fooMethod.invoke(fooClass.newInstance(), "I did it");
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
137840 次 |
最近记录: |