How to read convert String to JSON in Boost in Android - android

I have been trying to read JSON data from a JSON string, but my app keeps crashing immediately after it starts. No errors are displayed.
The JSON string is passed from the Javascript code in React Native :
let myJSONString = JSON.stringify({foo: "bar"});
The CMakeLists.txt file that sets up boost :
set(my_boost_dir ${CMAKE_CURRENT_SOURCE_DIR}/libs/ndk_25_boost_1.79.0)
set(MY_BOOST_LIBS_DIR ${my_boost_dir}/libs)
set(MY_BOOST_INC_DIR ${my_boost_dir}/include)
#-----------------------------------------
add_library (libboost_container SHARED IMPORTED)
set_target_properties( libboost_container PROPERTIES IMPORTED_LOCATION
${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_container.so
)
#-----------------------------------------
#-----------------------------------------
add_library (libboost_json SHARED IMPORTED)
set_target_properties( libboost_json PROPERTIES IMPORTED_LOCATION
${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_json.so
)
#-----------------------------------------
#-----------------------------------------
add_library (libboost_system SHARED IMPORTED)
set_target_properties( libboost_system PROPERTIES IMPORTED_LOCATION
${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_system.so
)
#-----------------------------------------
add_library( libboost_chrono SHARED IMPORTED)
set_target_properties(libboost_chrono PROPERTIES IMPORTED_LOCATION
${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_chrono.so
)
#-----------------------------------------
include_directories( ${MY_BOOST_INC_DIR}
)
This is how I try reading the JSON string :
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/json.hpp>
JNIEXPORT jstring JNICALL
Java_com_ca_com_1gen_1lib_1pers_c_1libs_1core_MyStringToJSON_myStringToJSON(JNIEnv *env,
jobject instance,
jstring myJSONStringEntity_)
{
const char *myJSONStringEntity = env->GetStringUTFChars(myJSONStringEntity_, 0);
// Short alias for this namespace
namespace pt = boost::property_tree;
// Create a root
pt::ptree root;
// Load the json file in this ptree
pt::read_json(myJSONStringEntity, root);
// Read values
std::string returnVal = root.get<std::string>("foo", 0);
return returnVal;
}
Where am I doing it wrong?
Thank you all in advance.

You're mixing Boost JSON (a JSON library) and Boost Property (a Property Tree Library). Only use the first!
Live On Coliru
#include <boost/json.hpp>
#include <boost/json/src.hpp> // for COLIRU (header-only)
#include <iostream>
#define JNIEXPORT
#define JNICALL
using jstring = std::string;
struct jobject { };
struct JNIEnv { char const* GetStringUTFChars(jstring const& s, int) { return s.data(); } };
JNIEXPORT jstring JNICALL
Java_com_ca_com_1gen_1lib_1pers_c_1libs_1core_MyStringToJSON_myStringToJSON(JNIEnv *env,
jobject /*instance*/,
jstring myJSONStringEntity_)
{
const char *myJSONStringEntity = env->GetStringUTFChars(myJSONStringEntity_, 0);
// Short alias for this namespace
namespace bj = boost::json;
// Create a root
bj::value root = bj::parse(myJSONStringEntity);
// Read values
std::string returnVal{root.at("foo").as_string()};
return returnVal;
}
int main() {
auto f = Java_com_ca_com_1gen_1lib_1pers_c_1libs_1core_MyStringToJSON_myStringToJSON;
std::cout << "Example: " << f(nullptr, {}, R"({"foo":"bar", "qux": [1,2,3]})") << "\n";
}
Prints
Example: bar

Related

App crashing upon calling server function

Trying to run local server from inside an android app, but the app keep trashing the time the button is clicked to run the server, my code is:
package tk.android
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Example of a call to a native method
findViewById<TextView>(R.id.sample_text).text = stringFromJNI()
btn.setOnClickListener {
txt.setText(reverse(txt.text.toString()))
server()
}
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
external fun stringFromJNI(): String
external fun server() : Void // extern void server(); // Here is the server
private external fun reverse(str: String): String // extern char* reverse(char* in)
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
The android app is built with Native where 3 functions are defined, 2 of then running smoothly, but the one related to the server is crasking.
My native functions are defined as:
// file cpp/native-lib.cpp
#include <jni.h>
#include <string>
#include "libfoo.h" // our library header
extern "C" JNIEXPORT jstring JNICALL
Java_tk_android_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C" {
jstring
Java_tk_android_MainActivity_reverse(JNIEnv* env, jobject, jstring str) {
// Reverse text here
const char* cstr = env->GetStringUTFChars(str, 0);
char* cout = reverse(const_cast<char*>(cstr));
jstring out = env->NewStringUTF(cout);
env->ReleaseStringUTFChars(str, cstr);
free(cout);
return out;
}
}
extern "C" {
void
Java_tk_android_MainActivity_server() {
// Nothing here, as it is void input and void output
server();
}
}
With the CMake file defined as:
cmake_minimum_required(VERSION 3.10.2)
project("android")
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
add_library(lib_foo SHARED IMPORTED)
set_property(TARGET lib_foo PROPERTY IMPORTED_NO_SONAME 1)
set_target_properties(lib_foo PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libfoo.so)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/)
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( # Specifies the target library.
native-lib
lib_foo
# Links the target library to the log library
# included in the NDK.
${log-lib} )
The server file I'm running is simple one built with GO, and compiled as shared library
package main
import "C"
// other imports should be seperate from the special Cgo import
import (
"fmt"
"log"
"net/http"
)
//export reverse
func reverse(in *C.char) *C.char {
return C.CString(foo.Reverse(C.GoString(in)))
}
//export server
func server() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func Reverse(in string) string {
n := 0
rune := make([]rune, len(in))
for _, r := range in {
rune[n] = r
n++
}
rune = rune[0:n]
for i := 0; i < n/2; i++ {
rune[i], rune[n-1-i] = rune[n-1-i], rune[i]
}
return string(rune)
}
func main() {}
Compiled to Android with the below Make file:
//file: Makefile
ANDROID_OUT=../myApp/app/src/main/jniLibs
ANDROID_SDK=$(HOME)/Library/Android/sdk
NDK_BIN=$(ANDROID_SDK)/ndk/23.0.7599858/toolchains/llvm/prebuilt/darwin-x86_64/bin
android-armv7a:
CGO_ENABLED=1 \
GOOS=android \
GOARCH=arm \
GOARM=7 \
CC=$(NDK_BIN)/armv7a-linux-androideabi21-clang \
go build -buildmode=c-shared -o $(ANDROID_OUT)/armeabi-v7a/libfoo.so ./cmd/libfoo
android-arm64:
CGO_ENABLED=1 \
GOOS=android \
GOARCH=arm64 \
CC=$(NDK_BIN)/aarch64-linux-android21-clang \
go build -buildmode=c-shared -o $(ANDROID_OUT)/arm64-v8a/libfoo.so ./cmd/libfoo
android-x86:
CGO_ENABLED=1 \
GOOS=android \
GOARCH=386 \
CC=$(NDK_BIN)/i686-linux-android21-clang \
go build -buildmode=c-shared -o $(ANDROID_OUT)/x86/libfoo.so ./cmd/libfoo
android-x86_64:
CGO_ENABLED=1 \
GOOS=android \
GOARCH=amd64 \
CC=$(NDK_BIN)/x86_64-linux-android21-clang \
go build -buildmode=c-shared -o $(ANDROID_OUT)/x86_64/libfoo.so ./cmd/libfoo
android: android-armv7a android-arm64 android-x86 android-x86_64
I do not know if there is something wrong in the definision of Java_tk_android_MainActivity_server() or it is crashing because the server will be listening to http signal!
I got the follwoing only once the app crash:
I/chatty: uid=10104(tk.android) Thread-2 identical 1 line
W/tk.android: Accessing hidden method
Landroid/database/sqlite/SQLiteDatabase;->yieldIfContendedHelper(ZJ)Z
(greylist-max-o, linking, denied)

I get java.lang.UnsatisfiedLinkError when try to call a native function from my project configured with bazel

I have created a cc_library in my bazel Build file and added the deps in android_binary rule
Bazel BUILD:
cc_library(
name = "native_libs",
srcs = glob([
"app/src/main/jni/**/*.cc",
"app/src/main/jni/**/*.h",
]),
)
android_binary(
name = "buildlib",
srcs = glob([
"app/src/main/java/**/*.java",
]),
manifest = "app/src/main/AndroidManifest.xml",
deps = ":native_libs",
)
And loaded the library in the specified package as
static{
System.loadLibrary("buildlib");}
And declares and calls the native function as :
Declaration:
private static native String foo(String code);
Function Call
foo("Code");
JNI FILE FUNCTION DECLARATION AND DEFINITION:
JNIEXPORT jstring JNICALL
Java_com_example_android_(foo)( JNIEnv* env, jobject thiz, jstring code );
JNIEXPORT jstring JNICALL
Java_com_example_android_(foo)( JNIEnv* env, jobject thiz, jstring code )
{
//some code
return code;
}
The library gets loaded successfully but while function call throws an error of java.lang.UnsatisfiedLinkError
How can i called the native foo() from my java file?

No implementation found

I have an Android app needs to reference and use some native C++ code. I'm an experienced Java dev, but my C++ is lacking. I'm struggling to get it to run. I'm getting the error below. If I change the name inside of loadLibrary, it crashes immediately, so I'm assuming that the load works fine. How do I fix this?
No implementation found for boolean com.example.myapplication.BamBridge.test() (tried Java_com_example_myapplication_BamBridge_test and Java_com_example_myapplication_BamBridge_test__)
public class BamBridge implements IBamBridge {
static {
System.loadLibrary("native-lib");
}
private native boolean test();
}
BAM.h:
#ifndef BAM_H
#define BAM_H
#define JNIIMPORT
#define JNIEXPORT __attribute__ ((visibility ("default")))
#define JNICALL
#include <set>
#include <vector>
#include <string>
extern "C" JNIEXPORT JNICALL bool test();
#endif
BAM.cpp
#include <cstdio>
#include <stdint.h>
#include <iostream>
#include <map>
#include "BAM.h"
#define SWAP_UINT16(val) ((val << 8) | (val >> 8))
JNIEXPORT JNICALL bool test()
{
return true;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.6.0)
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/BAM.cpp )
On the C side change your function name to
Java_com_example_myapplication_BamBridge_test
As java searches for the function in the specific format.
In your Header file:
extern "C"
{
JNIEXPORT jboolean JNICALL Java_com_example_myapplication_BamBridge_test(JNIEnv *, jobject);
}
In your CPP file:
extern "C"
{
jboolean Java_com_example_myapplication_BamBridge_test(JNIEnv * env, jobject this)
{
return true;
}
}

Calling C++ function from a C file in Android

I am doing development in Android using C/C++. I have a C++ function, that needs to be called from a C file. Here is what I am doing right now, but I get the error
undefined reference to __check_expiry
The C++ function is defined in "a.h" and implemented in "a.cpp". I am including "a.h" in"b.c" file and calling the method "__check_expiry" from "b.c" file.
a.h :
#ifdef __cplusplus
extern "C" {
#endif
static int __check_expiry(void);
#ifdef __cplusplus
}
#endif
a.cpp:
extern "C" {
static int __check_expiry() {
vz::lock_guard<std::mutex> guard(mutex_check, lock_hooker_check);
JNIEnv *env = NULL;
static bool __is_attached_1 = false;
if ((env = __getEnv(&__is_attached_1)) == NULL) {
//log_info("getEnv fail\r\n");
}
assert(!__is_attached_1);
int obj = env->CallStaticIntMethod((jclass) g_class, g_methodID);
log_info("Returned value from JAVA %d", obj);
__releaseEnv(__is_attached_1);
guard.~lock_guard();
return obj;
}
}
b.c:
#ifdef __cplusplus
extern "C" {
#endif
#include "a.h"
#ifdef __cplusplus
}
#endif
static int tunnel_to()
{
int value = __check_expiry();
}
Static functions are not exported. Remove the static qualifier.
(Unrelated: as long as you #include "a.h" from a.cpp, you don't need the extern "C" in your source file.)

Android NDK: Passing data from Java to C++/C

I have already tried NDK simple examples such as displaying data from a native code to android's java code such as this:
#include <jni.h>
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_JNIActivity_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return env->NewStringUTF("I'm C++! What the hell am I doing here in android?!");
}
}
However, I want an application wherein user will have to enter data from a textfield and have this data be pass from it's java code to the native code where calculations will be done. How will I do this?
In your Java native method, include a formal String argument that accepts the textfield value.
In C/C++, access the characters from the jstring with JNI methods like these:
jsize GetStringLength(JNIEnv *env, jstring string);
const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);
When you're done with the characters, be sure to release them.
void ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars);
void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf);
See the documentation for these methods in the Java Native Interface Specification.

Categories

Resources