我希望看到一个用C/C++编写的"Hello world"程序,但可以在Android上运行.
我知道这可以通过使用NDK和JNI调用来实现.但是无法使其发挥作用.没有在线指南是有帮助的.
需要知道才能开始.
我正在使用Windows 7计算机进行开发,并且还使用Eclipse轻松实现.
Android安装路径:C:\ Program Files\Android\android-sdk-windows和NDK我已经提取到:C:\ Program Files\Android\android-ndk-r5
如果我可以帮助运行一个简单的"hello world",我可以使用C++设计大部分敏感代码.
所有ndk示例仅使用在标头中声明为extern并在cpp文件中定义的基本C函数.然后将头文件包含在包含jni回调的C文件中后,一切正常.
可以在android ndk中使用C++类吗?我的应用程序不会是本机活动,它仍然会有一个重要的Java部分,但它会调用本机C代码进行CPU密集型计算(已经用C++编写,包含类和其他C++东西).
现在这是我的hello-world,就像strcuture:
文件"first.h"
#ifndef FIRST_H
#define FIRST_H
class Test
{};
#endif /* FIRST_H */
Run Code Online (Sandbox Code Playgroud)
档案"second.cpp"
#include <jni.h>
#include "first.h"
#ifdef __cplusplus
extern "C" {
#endif
jint Java_com_example_twolibs_TwoLibs_add( JNIEnv* env,
jobject this,
jint x,
jint y )
{
Test t;
return 0;
}
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
最后是Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libtwolib-second
LOCAL_SRC_FILES := second.cpp
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
非常基本,但不编译.在包含头文件时,转换.c文件中的second.cpp会引发错误,我想这是因为它不是C++文件.
error: expected '=', ',', ';', 'asm' or '__attribute__' before 'Test'
Run Code Online (Sandbox Code Playgroud)
使它.cpp引发以下错误:
make: *** No rule to …Run Code Online (Sandbox Code Playgroud) 有没有人有一个很好的解决方案将一些C#代码集成到一个Java应用程序?
代码很小,所以我可以用java重写,但如果可能的话我宁愿重用代码.不要重复自己,等等.
此外,我知道我可以将C#作为Web服务或其他任何东西公开,但它有一些安全/加密的东西,所以我宁愿保持紧密集成,如果可能的话.
编辑:它将在基于服务器的应用程序上,因此"下载"另一个运行时无关紧要.
JNI教程,例如本教程,很好地介绍了如何访问对象中的原始字段,以及如何访问作为显式函数参数提供的数组(即作为子类jarray).但是如何访问作为字段内的字段的Java(原始)数组jobject?例如,我想操作以下Java对象的字节数组:
class JavaClass {
...
int i;
byte[] a;
}
Run Code Online (Sandbox Code Playgroud)
主程序可能是这样的:
class Test {
public static void main(String[] args) {
JavaClass jc = new JavaClass();
jc.a = new byte[100];
...
process(jc);
}
public static native void process(JavaClass jc);
}
Run Code Online (Sandbox Code Playgroud)
相应的C++方面将是:
JNIEXPORT void JNICALL Java_Test_process(JNIEnv * env, jclass c, jobject jc) {
jclass jcClass = env->GetObjectClass(jc);
jfieldID iId = env->GetFieldID(jcClass, "i", "I");
// This way we can get and set the "i" field. …Run Code Online (Sandbox Code Playgroud) 这是我第一次使用JNI,也是我第一次在C中写一些行.
我想要做的很简单.我只是尝试使用C例程切换byte []的endiannes.
在java中,它是这样完成的:
public void switchEndianness(byte[] array){
byte byte1;
byte byte2;
for(int i = 0; i < array.length ; i+=2){
byte1 = array[i];
byte2 = array[i+1];
array[i] = byte2;
array[i+1] = byte1;
}
}Run Code Online (Sandbox Code Playgroud)
所以为了使用JNI做到这一点,我试图在JNICALL中使用相同的例程,但是它没有编译.到目前为止我写的是这样的:
JNIEXPORT void JNICALL Java_CEndianness_switchEndianness(JNIEnv *env, jobject obj, jbyteArray array, jint offset, jint length){
char byte1;
char byte2;
int i;
for(i = offset; i < length ; i+=2){
byte1 = array[i];
byte2 = array[i+1];
array[i] = byte2;
array[i+1] = byte1;
}
}Run Code Online (Sandbox Code Playgroud)
我不知道如何使用jbyteArray类型的数据.是否可以将jbyte存储在char中?另一个问题是..当这个例程结束时... java中的byte []会被修改吗?或者它只在C调用内修改? …
所以我在C中使用以下代码利用Java Native Interface但是我想将其转换为C++,但我不确定如何.
#include <jni.h>
#include <stdio.h>
#include "InstanceMethodCall.h"
JNIEXPORT void JNICALL
Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
if (mid == NULL) {
return; /* method not found */
}
printf("In C\n");
(*env)->CallVoidMethod(env, obj, mid);
}
Run Code Online (Sandbox Code Playgroud)
Java程序:
class InstanceMethodCall {
private native void nativeMethod();
private void callback() {
System.out.println("In Java");
}
public static void main(String args[]) {
InstanceMethodCall c = new InstanceMethodCall();
c.nativeMethod();
}
static {
System.loadLibrary("InstanceMethodCall");
}
} …Run Code Online (Sandbox Code Playgroud) 使用JNI我们可以将自定义数据类型从Java传递到C(反之亦然)吗?我看到原始数据类型到C中的类型的映射,但是我们不能确定是否可以发送我们自己的数据类型(例如发送或返回一个Employee对象或其他东西!).
我一直在关注本教程,在第5步,我从GCC获得以下输出:
HelloWorld.c:1:17: error: jni.h: No such file or directory
In file included from HelloWorld.c:3:
HelloWorld.h:15: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
HelloWorld.c:5: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
Run Code Online (Sandbox Code Playgroud)
我知道他包含的目录因系统而异,所以我尝试相应地调整命令,但我似乎无法在我的系统上找到正确的目录.我正在使用Ubuntu 10.04LTS.
似乎大多数与JNI(Java Native Interface)相关的文档或帮助程序库都涉及从Java调用本机代码.这似乎是它的主要用途,即使它能够更多.
我想主要在相反的方向上工作:通过向其添加一些Java库来修改现有的(相当大的)可移植C++程序.例如,我想让它通过JDBC调用数据库,或者通过JMS调用消息队列系统,或发送电子邮件,或调用我自己的Java类等.但是使用原始JNI这是非常不愉快和容易出错的.
所以我理想地想编写可以像C++/CLI一样调用CLR类的C++代码来调用Java类.就像是:
using namespace java::util::regex; // namespaces mapped
Pattern p = Pattern.compile("[,\\s]+");
array<java::lang::String> result =
p.split("one,two, three four , five");
for (int i=0; i < result.length(); i++)
std::cout << result[i] << std::endl;
Run Code Online (Sandbox Code Playgroud)
这样,我就不必通过传递名称和奇怪的签名字符串来手动完成获取方法ID的工作,并且可以防止由未经检查的API调用方法引起的编程错误.实际上它看起来很像等效的Java.
NB.我还在谈论使用JNI!作为一项基础技术,它非常适合我的需求.它"在进行中"并且高效.我不想在一个单独的进程中运行Java并对它进行RPC调用.JNI本身很好.我只想要一个愉快的界面.
必须有一个代码生成工具来创建等效的C++类,命名空间,方法等,以完全匹配我指定的一组Java类所公开的内容.生成的C++类将:
这样一个免费的,开源的,可移植的库/工具是存在还是我在做梦?
注意:我发现了这个现有的问题,但在那种情况下,OP并不像我一样对完美的要求......
更新:关于SWIG的评论引发了我之前的问题,这似乎表明它主要是相反的方向,所以不会做我想要的.
重要
更新:我已经开始研究自己的解决方案了:
https://github.com/danielearwicker/cppjvm
如果这已经存在,请告诉我!
NB.如果您正在考虑在自己的项目中使用它,请自由,但请记住,现在代码已经有几个小时了,到目前为止我只编写了三个非常不费力的测试.
我试图在Windows 7操作系统上从命令行使用javah工具创建头文件,但我一直都失败了.
我有不同的方法,甚至从oracle阅读javah工具的文档,但他们没有帮助克服这个问题.
我的类file(hellojni.class)和java file(hellojni.java)都在D:\驱动器的根目录中.
但每当我运行javah工具时它会给我一个错误:
找不到hellojni的类文件
我尝试提供类路径,但没有得到任何头文件.