I’m encountering an issue with linking C libraries in my Android project using the Android NDK r8b.
I built with the toolchain for ARM the cURL library (no SSL) and it provided me a libcurl.a file and a libcurl.so.4.2.0 one.
I also created a C file to provide functions to my Java code and to use the cURL library.
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libcurl
LOCAL_SRC_FILES := libcurl.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := curljni
LOCAL_SRC_FILES := curljni.c
LOCAL_STATIC_LIBRARIES := libcurl
include $(BUILD_SHARED_LIBRARY)
and now my C file
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
jstring Java_test_curljni_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
CURL *curl;
CURLcode
......
}
When I try to build with the ndk-build command from my project folder, here’s the output error :
Compile thumb : curljni <= curljni.c
jni/curljni.c: In function 'Java_test_curljni_MainActivity_stringFromJNI':
jni/curljni.c:8:3: error: unknown type name 'CURL'
jni/curljni.c:9:3: error: unknown type name 'CURLcode'
jni/curljni.c:11:8: warning: assignment makes pointer from integer without a cast [enabled by default]
jni/curljni.c:13:28: error: 'CURLOPT_URL' undeclared (first use in this function)
jni/curljni.c:13:28: note: each undeclared identifier is reported only once for each function it appears in
/cygdrive/c/android-ndk-r8b/build/core/build-binary.mk:252: recipe for target `obj/local/armeabi/objs/curljni/curljni.o' failed
make: *** [obj/local/armeabi/objs/curljni/curljni.o] Error 1
I’ve tried many things within the Android.mk file, nothing successful. Using a PREBUILT_SHARED_LIBRARY doesn’t help because it requires a .so file only and changing the extension from .so.4.2.0 to .so just tells me that the format is not supported when building …
One thing I’m not sure about if whether I have to include the headers in my C file, but when I do it, it ofcourse don’t find them.
As a note, when I build with only the curl library declared in my Android.mk file (the shared library with the C file is ommitted) then nothing is created in the libs folder !
Thanks in advance for your help !
EDIT ::::
Actually it did work mbrenon (I’ve tried it millions time and now it works, no idea what’s different), but now I have
c:/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../. ./arm-linux-androideabi/bin/ld.exe: cannot find ./obj/local/armeabi/libcurl.a: Permission denied
I’m using Cygwin, could that be why I encounter permission issues ?
I manage to get around it when the .so and the .a are created, returning the permission error, chmod on it and running the ndk-build again, but that seems a bit rough !
Plus now none of my curl functions can be reached (“undefined reference to (function)”).
$ ../../../ndk-build
SharedLibrary : libcurljni.so
./obj/local/armeabi/objs/curljni/curljni.o: In function `Java_test_curljni_MainActivity_stringFromJNI':
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:12: undefined reference to `curl_easy_init'
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:14: undefined reference to `curl_easy_setopt'
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:15: undefined reference to `curl_easy_perform'
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:17: undefined reference to `curl_easy_cleanup'
collect2: ld returned 1 exit status
/cygdrive/c/android-ndk-r8b/build/core/build-binary.mk:378: recipe for target `obj/local/armeabi/libcurljni.so' failed
make: *** [obj/local/armeabi/libcurljni.so] Error 1
and my curljni.c is the following
jstring Java_test_curljni_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
CURL *curl;
CURLcode res;
char buffer[10];
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "yahoo.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if(res == 0)
return (*env)->NewStringUTF(env, "0 response");
else
sprintf(buffer,"code: %i",res);
return (*env)->NewStringUTF(env, buffer);
}
else {
return (*env)->NewStringUTF(env, "no curl");
}
}
I made sure every needed function is declared in the curl.h
Yes, you do have to include the Curl headers in your C file. To allow ndk-build to find these header files at link time, you’ll have to add their path using LOCAL_EXPORT_C_INCLUDES:
This will automatically add the path to the headers in all the targets requiring libcurl, and it should build and link.