I am trying to work out why the following code won't work under JNI / Android.
If I uncomment the 'raw_function()' from the code below, the code fails to compile with the following message:
Error:error: linker command failed with exit code 1 (use -v to see invocation)
I have two problems:
1) I have no idea how to use -v to see invocation - where would I do this?
2) I have no idea why the code is not compiling when I uncomment that specific line. Moving that function into the class (Header_Test) also fixes the problem, but why?
I have included pretty much everything from the project below. The only areas of interest should be header_test.h and native-lib.cpp.
I realize that putting a function in the global namespace is bad practice. This code is purely for test purposes.
header_test.h
#ifndef TESTCPLUSPLUSCHRONO_HEADER_TEST_H
#define TESTCPLUSPLUSCHRONO_HEADER_TEST_H
#include <string>
class Header_Test {
public:
static std::string get_name() {
return "Header Test";
}
};
/*std::string raw_function() {
return "Raw function";
}
#endif //TESTCPLUSPLUSCHRONO_HEADER_TEST_H
native-lib.cpp
#include <jni.h>
#include <string>
#include "header_test.h"
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_test_android_testrawfunctiontest_MainActivity_stringFromJNI(
JNIEnv *env,
jobject) {
std::string hello;
hello = Header_Test::get_name();
return env->NewStringUTF(hello.c_str());
}
header_test.cpp
#include "header_test.h"
MainActivity.java
package com.test.android.testrawfunctiontest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
String jniText = stringFromJNI();
tv.setText(jniText);
String filler = "-------------------";
System.out.println(filler);
System.out.println("Text from JNI: " + jniText);
System.out.println(filler);
}
public native String stringFromJNI();
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp
src/main/cpp/header_test.cpp )
find_library(log-lib log )
target_link_libraries(native-lib ${log-lib}
I am sure if I understood what exactly I was asking, I would be able to word this a lot better. I've run a lot of searches trying to find an answer for this, but I don't even know how to phrase the search.
Any comments pointing me in the right direction for this would be appreciated.
Your raw_function()
'appears' twice for the linker: once, from file native-lib.cpp, and also, from header_test.cpp. To avoid the clash, you can declare it either inline
or static
. The result will be different: in the latter case, your native-lib will have two independent functions raw_function()
, each visible from its own cpp file:
inline std::string raw_function() {
return "Raw function";
}
or
static std::string raw_function() {
return "Raw function";
}