I have managed to get SQLite setup using the NDK, but I can't manage to get custom functions to work which was the whole reason for implementing SQLite using the NDK.
I used this library to get the same SQLite files. It also contains an extension file called extensionfunctions.c which adds in string and mathematical functions for SQLite.
From what I can see, the SQLite implementation appears to be working correctly, but I cannot call any of the custom functions.
I've little to no knowledge of C/C++, so any help would be great. Do I have to compile the extensionfunctions.c file independently, and then add in the SO file with the libsqliteX.so file? Or do I have to make a call in the android_database_SQLiteCommon.cpp to load in the other extension? I've no idea how this works.
Edit
The file extensionfunctions.c is included in sqlite3secure.c which is in the Android.mk file under LOCAL_SRC_FILES. I assume that means the file is being used correctly, but none of the custom functions are accessible.
Edit 2
// To enable the extension functions define SQLITE_ENABLE_EXTFUNC on compiling this module
#ifdef SQLITE_ENABLE_EXTFUNC
#define sqlite3_open sqlite3_open_internal
#define sqlite3_open16 sqlite3_open16_internal
#define sqlite3_open_v2 sqlite3_open_v2_internal
#endif
#include "sqlite3.c"
#ifdef SQLITE_ENABLE_EXTFUNC
#undef sqlite3_open
#undef sqlite3_open16
#undef sqlite3_open_v2
#endif
I found the above code with the comment and I added in the line below but it appears as though nothing has changed.
#define SQLITE_ENABLE_EXTFUNC
Do I have to do anything to get the app to refresh it's version of the sqlite3 files or could that be a problem? My C skills are poor so I assume what I did is what the comment has referring to?
Related
I have a JNI function in a C++ library.
When I create the library using cmake (but forget to put function declaration) in the header file, the library is created successfully.
When I look for function name in library symbol table I get following output
nm libuserlibrary.so | grep printxx
00506e60 T _Z60Java_com_example_user_myapplication_userlibrary_printxxP7JNIEnv_P8_jobject
But when I give function declaration in the header file, I get following output
nm libuserlibrary.so | grep printxx
00506e50 T Java_com_example_user_myapplication_userlibrary_printxx
Why is there this difference between these two symbol table entries? What is the purpose of _Z60 and P7JNIEnv_P8_jobject around the function name?
I also noticed that in the first case, I cannot call the JNI funciton from Android java code (it says unsatisfied-linker-error, implementation not found).
C++ allows function overloads and namespaces like Java does. So, it annotated the function name with parameter information so the linker can bind to the correct overload.
JNI was designed for C which does not allow function overloads or namespaces. So it invented it's own annotation system and provides the javah tool to help you use it. The header can be used in C++ too. C++ was designed to allow some functions to be called as if they written in C. The header has code that indicates that to the compiler. So, put it all together and you can write Java-callable functions in C++.
I am trying to use a hash_map, defined in the Android NDK, but I get a "deprecation warning":
ndk/sources/cxx-stl/gnu-libstdc++/4.6/include/ext/../backward/backward_warning.h:33:2:
error: #warning This file includes at least one deprecated or antiquated header which may
be removed without further notice at a future date. Please use a non-deprecated interface
with equivalent functionality instead. For a listing of replacement headers and
interfaces, consult the file backward_warning.h. To disable this warning use -Wno-
deprecated. [-Werror=cpp]
And since "unordered_map" is present in gnu-libstdc++/4.6/include/ and also in gnu-libstdc++/4.6/include/tr1/, I believe that there is a way to use it.
The point is that I cannot find it. Which of the following is the right one (if any):
#include <tr1/unordered_map.h>
#include <unordered_map>
And then, how to use it? __gnu_cxx::unordered_map is not recognized... and I don't know how to find this information.
In case you don't want/need C++11 support, you can use the one from the STLPort using:
// Here we are referencing the stlport one:
#include <unordered_map>
...
std::tr1::unordered_map<int, int> test;
That's because STLPort defines unordered_map inside tr1 namespace, but the STLPort header is not inside any /tr1/ folder.
I eventually found a way by adding C++11 support in my Android project. Pretty easy when we know it, but I took some time to figure it out. Neither STLPort nor Boost were needed. Once C++11 was integrated, I could use "unordered_map" as follows:
#include <unordered_map>
...
std::unordered_map<int, int> test;
I created a new question to explain how to enable C++11 support in Android here.
I'm just messing around with a Ndk tutorial I found. The native code uses one "package", while the activity is in another. When this mismatch occurs, I can't call the native function without getting an unsatisfied link exception. I know the "why's" I just don't know the resolution.
Here is the sample .c code that I've placed in my jni folder:
#include <string.h>
#include <jni.h>
jstring Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
return (*env)->NewStringUTF(env, "Hello from native code!");
}
Notice that this .c code's package translates to com.mindtherobot.samples.ndkfoo.NdkFooActivity.
If I create a new activity that matches that Package/Class, I can call the invokeNativeFunction just fine. However, what if I can't match it? What if instead I need to run it from com.mydomain.activity?
I figured I could maybe change things around, such that my native declaration looked like this:
package com.mydomain;
public class Activity {
private native String com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction();
}
But that's a no-go. Just to be clear, I know how to make this work if I change my package to match what is compiled in the .c code; however, I need to be able to call a method from a different package... is this possible?
You need to make a basic class with the sole functionality of talking to C, not an activity. Then activities can instantiate this class, or possibly even statically call it, whenever they need to talk to C.
Your question is pretty scrambled, but the package declaration in the Java source code has to agree with what is encoded into the native method name, i.e. it must agree with what is generated by javah. If you change the package in the Java code, you must regenerate the .h file, and adjust the .c file to suit. There is no other way to fudge around this.
I am building C++ code that is used on both android and iOS. I need some form of debugger macro to insert debugging easily into the code.
For example, I was thinking of something like this:
#ifdef ANDROID
# define MY_DEBUG(debugmsg) __android_log_print(ANDROID_LOG_INFO, ANDROID_DEBUG_TAG,debugmsg)
# define MY_DEBUG(debugmsg, mystr) __android_log_print(ANDROID_LOG_INFO, ANDROID_DEBUG_TAG,debugmsg,mystr)
#elif defined (iOS)
# define MY_DEBUG(debugmsg) printf(debugmsg)
# define MY_DEBUG(debugmsg, mystr) printf(debugmsg, mystr)
#endif
So for example I could use MY_DEBUG("hello %s","world") and MY_DEBUG("hello")
However it complains about macro redefinition (and rightfully so). How do I make a macro.. 'overload', or accept more than one parameter if entered?
Also - does printf() send data to the iOS console?
You can't overload macros the way you can with functions because the preprocessor has not changed significantly, if at all, since C. A common approach is to use MY_DEBUG and MY_DEBUG2 etc.
There are variatic macros but I avoid them in multi-platform code.
I'm doing some cross platform development, and I ran across another weird problem..
namespace Math
{
#include <math.h>
}
This is what I am trying to do. It works fine on iOS, but on Android everything inside math.h is not a member of Math when I try to compile it. After some trial an error I found out that the ndk doesn't put the stuff in math.h in the namespace Math, as the functions do exist without the Math:: prefix. The big problem is that some functions in math.h clash with my own convenience functions. How can I fix this?
You really shouldn't try to put any system headers into a different namespace. The solution, as painful as it may be at this point in development, is to put all of your code into its own namespace.
What about <cmath>? it puts everything in std:: (in C++11).
Don't put your convenience functions in the global namespace.
Don't try to wrap math.h in a namespace.
There, all’OK now.
Cheers & hth.,
Probably something else includes math.h earlier in the preprocessor "pipeline". C includes check whether the sane include has been included earlier. In this case, the check #ifndef MATH_H resulted in excluding the whole file. Try placing your include with the namespace at the beginning of your .c files.