此代码使用C ++代码调用Linux命令,但是如何通过NDK将其转换为lib? 我看到只使用.C文件的例子,以及Jni使用的与C ++变量不同的变量。
这个c ++代码,我需要将其转换为使用它然后使用NDK
#include <string>
#include <iostream>
#include <stdio.h>
std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
这适合吗?
Android.mk 中的
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := NDK1
LOCAL_SRC_FILES := NDK1.cpp
include $(BUILD_SHARED_LIBRARY)
假设我的原生方法是exec(char * cmd), 对于 NDK1.cpp
#include <string>
#include <iostream>
#include <stdio.h>
#include <jni.h>
jstring Java_com_mindtherobot_samples_ndkfoo_MainActivity_exec(JNIEnv* env, jobject javaThis , Jchar* cmd) {
......... same code above
return result;
}
如何安排这些文件以获得正确的解决方案?
答案 0 :(得分:3)
您仍然需要使用本机方法声明的MainActivity java代码。我不知道你是不是发帖,或者你忘了实施它。它应该是这样的:
public class MainActivity extends Activity
{
/*Don't forget to load the library!!*/
static {
System.loadLibrary("NDK1");
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// your initialization here...
}
public native String exec(String cmd);
}
另外,正如g-makulik在评论中指出的那样,你在本机代码中返回一个c ++字符串,但你应该返回一个Java字符串。 NDK1.cpp文件应该与此类似:
#include <string>
#include <iostream>
#include <stdio.h>
#include <jni.h>
std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
jstring Java_com_mindtherobot_samples_ndkfoo_MainActivity_exec(JNIEnv* env, jobject javaThis , Jchar* cmd) {
std::string result = exec(cmd);
return (*env)->NewStringUTF(env, result);
}
最后,您应该运行ndk-build脚本来为您的代码生成共享库。确保将NDK1.cpp文件放在与Android.mk文件相同的目录中,位于jni文件夹中(假设您不想更改Android.mk文件以查找其他位置的源)。 假设您正在使用Linux(我不知道它如何适用于Windows),您应该打开一个终端,您拥有Android.mk。在那里你必须运行'ndk-build'命令。如果一切正常,您将不会收到任何错误,.so文件将被复制到项目的libs文件中。
更新: 也许你需要添加stl库来使用字符串类。您可以尝试使用以下内容在与Android.mk相同的目录中添加Application.mk文件:
APP_ABI := armeabi armeabi-v7a
APP_STL := gnustl_static
答案 1 :(得分:0)
Android不允许直接从内部或外部存储中读取文件。这就是为什么所有人都使用Android操作系统,因为它阻止了安全漏洞。如果您想要使用c ++本机代码读取文件,则必须使用C ++中的Java Api调用。
AAssetManager* mgr = AAssetManager_fromJava(env,assetManager);
AAsset* asset = AAssetManager_open(mgr,"textfile.txt", AASSET_MODE_UNKNOWN);
if (NULL == asset) {
return; //exit with error not loaded
}
long size = AAsset_getLength(asset);
char* buffer = (char*) malloc (sizeof(char)*size);
AAsset_read (asset,buffer,size);
AAsset_close(asset);
free(buffer);
就是这样。您还必须从java
传递assetManagerpublic native void readTxtFile(AssetManager assetManager);
并使用此功能获取资源
AssetManager assetMgr; //define this as global variable
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
assetMgr = getResources().getAssets(); //very important dont forget!
readTxtFile(assetMgr);
}
你还必须在Eclipse中的Android.mk或android {}标签内的Build.gradle(Android Studio)中添加链接器“log”和“android”libs
ndk {
moduleName "your_module_name"
ldLibs "android","log"
//ldLibs.add("android")
}
如果您在Android Studio中使用外部CMakeList.txt
find_library( # Sets the name of the path variable.
android-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
android )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( native-lib
${log-lib}
${android-lib})
你也必须像这样声明Jni c ++函数
void Java_com_example_lenovo_firstopencv_MainActivity_salt(JNIEnv *env,
jobject instance,jobject assetManager) { /*copy above c++ code to here*/}
不要忘记在主文件夹中创建assets文件夹,因为您的文件(textfile.txt)位于assets文件夹中,assetmanager对象从那里读取。 这就对了。我花了2天时间编写这段代码。享受并支持OpenSource;)