undefined lame decode function - android

I'm trying to add MP3 read and write capabilities to my Android app. I'm using the lame4android app as a starting point. Encoding a file works for me, but I'm having a problem with the decode functions -- I'm getting undefined references to the decode functions.
Here are excerpts from my wrapper.c:
#include "libmp3lame/lame.h"
#include "jni.h"
lame_t lame;
jint Java_com_intonia_dandy_WavStream_initEncoder(JNIEnv *env,
jobject jobj,
jint in_num_channels,
jint in_samplerate)
{
lame = lame_init();
...
return lame_init_params(lame);
}
hip_t hip;
jint Java_com_intonia_dandy_WavStream_initDecoder(JNIEnv *env, jobject jobj)
{
hip = hip_decode_init();
return hip != 0;
}
And here are the declarations from lame.h:
lame_global_flags * CDECL lame_init(void);
typedef hip_global_flags *hip_t;
hip_t CDECL hip_decode_init(void);
I'm getting an error message:
C:/ACode/dandy/src/main/jni/./wrapper.c:62: undefined reference to `hip_decode_init`
I'm also getting undefined references to hip_decode and and hip_decode_exit. But lame_init, lame_init_params, lame_encode_buffer, and lame_encode_flush do not generate any errors. I get these errors using the command line to run ndk-build, and I get the same errors when I let Android Studio manage the compilation.
How are the lame_* functions different from the hip_decode_* functions? Should I be using the deprecated lame_decode_*?
EDIT: I'm looking at the output of the ndk-build command. The .c files are listed on the console as they are compiled. hip_decode_init is defined in jni/libmp3lame/mpglib_interface.c, but mpglib_interface is not getting compiled, even though it's listed in jni/Android.mk. Why not???

It turns out that the LAME library as distributed does not have decoding enabled. To get it working, I had to do the following:
Add #define HAVE_MPGLIB 1 to mpglib_interface.c
Copy all .c and .h files from the mpglib directory of the LAME distribution.
Edit Android.mk to include the .c files from mpglib.
EDIT: instead of modifying mpglib_interface.c to define HAVE_MPGLIB,
it's better to set compilation flags.
Working with Android Studio 2+, build.gradle should contain
android {
defaultConfig {
ndk {
moduleName "libmp3lame"
cFlags "-DSTDC_HEADERS -DHAVE_MPGLIB"
}
}
}
Or in Android.mk:
LOCAL_CFLAGS = -DSTDC_HEADERS -DHAVE_MPGLIB

Related

Linker can't find function

Im trying to build an Ubuntu Touch tree, based on an Aosp tree I already correctly built.
It fails with this error
CAPEWrapper.cpp:16: error: undefined reference to '__xlog_buf_printf'
this is the header that file includes
#include "CAPEWrapper.h"
which on cascade includes
#include <cutils/xlog.h>
which in turn defines
#if defined(__cplusplus)
extern "C" {
#endif
int __xlog_buf_printf(int bufid, const struct xlog_record *rec, ...);
#if defined(__cplusplus)
}
#endif
I suspect that my g++ doesn't set __cplusplus macro. Could it be a realistic scenario with this kind of error? If this could be the problem, should I need to specify a standard implementation with "stdc=something" to solve it?
Any other idea is welcome.
Make sure that your project is linking libcutils, and that it's linking it in the correct order (i.e. that -lcutils appears in the linker command line after any module that depends on it).
In the end, I found that the modules was listed inside a macro called LOCAL_WHOLE_STATIC_LIBRARIES, that in Android environment passes its content to the --whole-archive flag of GCC linker.

Unresolved symbols NewShortArray and SetShortArrayRegion

I'm trying to use short[] and jshortArray between C/JAVA as follows in Eclipse:
JNIEXPORT void JNICALL Java_com_testingForFun_testFunc
(JNIEnv *env, jclass clazz, jshort num, jshortArray data) {
jshort outCArray[] = {100, 200};
jshortArray outJNIArray = (*env)->NewShortArray(env, 2); // allocate
if (NULL == outJNIArray) return;
(*env)->SetShortArrayRegion(env, outJNIArray, 0 , 2, outCArray); // copy
//return outJNIArray;
}
I've created the header file using javah and included it. However, Eclipse says NewShortArray and SetShortArrayRegion are unresolved and I can't build the apk. However, not using arrays (jshort and short) works fine. I looked in jni.h and it seems that NewShortArray other related functions are defined if __cplusplus is defined, but I'm using C. I also built the apk on the command line using ndk-build and ant and I read outJNIArray[0] or [1] = 0 in the calling function, so it's not working there either. How do I resolve this issue?
Additionally, Eclipse can't resolve ANDROID_LOG_DEBUG in:
__android_log_print(ANDROID_LOG_DEBUG, "FibLib.c", "fibNI(%lld)", n);
even though
#include <android/log.h>
is at the beginning of the file.
I used Eclipse restart and seems to have cleared up these issues. But every time I edit my .c file, the unresolved errors pop up, and I need to restart. It's very annoying. Any fix for this?
The issue of outJNIArray[] not being set is a separate topic, so I will ask another question on the forum in the future if necessary.

NDK unable to deal with #include with relative paths?

I'm writing an Adroid app with some C++ code behind the UI using Eclipse + NDK (r8d). I have some code that I thought was fool proof but the compiler just gives me weird errors like "Invalid arguments" without specifics. Here is what my C++ code looks like:
#include <jni.h>
#include <string>
using namespace std;
#include "../../Evaluator.Engine/Evaluator.Engine.h"
Evaluator evaluator;
extern "C" {
JNIEXPORT jstring JNICALL Java_haskellevaluator_android_MainActivity_evaluateNative(JNIEnv *env, jobject, jstring jInput)
{
...
string sInput(L"Hello world");
string sResult = evaluator.evaluate(sInput);
jstring jResult = env->NewStringUTF(sResult.data());
return jResult;
}
}
Evaluator.Engine.h is nothing fancy, but just a declaration of the class Evaluator.
#include <string>
using namespace std;
class Evaluator
{
public:
string evaluate(string input);
};
However, the compiler complains:
Invalid arguments '
Candidates are:
? evaluate(?)
'
as if string is not defined. But if I put a copy of the header file under the same folder, the error goes away. This is a Windows box. I have tried using \ and escaped \\ as path separators and it didn't work.
Does this sound like a NDK (or whatever the preprocessor it uses) bug? I don't want to move the header file because it'll be shared by other projects. I also hate to keep 2 copies of the same file.
Any ideas? Thanks.
Sorry I don't have windows OS, but I've tried you code on a MacOS, but it doesn't work because of:
string sInput(L"Hello world");
Saying that wchar_t cannot be put on std::string. Is it possible to be the same problem ?

include .h file into java file in android using jni as source folder of .h file?

void ProcedureParams_Initialize(ProcedureParams* pVal);
flag ProcedureParams_IsConstraintValid(const ProcedureParams* val, int* pErrCode);
flag ProcedureParams_XER_Encode(const ProcedureParams* val, ByteStream* pByteStrm, int* pErrCode, flag bCheckConstraints);
flag ProcedureParams_XER_Decode(ProcedureParams* pVal, ByteStream* pByteStrm, int* pErrCode);
flag ProcedureParams_BER_Encode(const ProcedureParams* val, ByteStream* pByteStrm, int* pErrCode, flag bCheckConstraints);
flag ProcedureParams_BER_Decode(ProcedureParams* pVal, ByteStream* pByteStrm, int* pErrCode);
typedef struct {
GeneralEvthParams g_params;
DataParams d_params;
} EvtHandlerParams;
how i can add .h file directly into my .java file. i'm using NDk and .h file inside my jni folder.i want to use the functions of header file . how i can directly use functions in java activity? please help me
You cannot invoke the C/C++ functions directly. The C implementations of Java native functions all have a very specific set of parameters:
JNIEXPORT jint JNICALL Java_com_mycompany_MyClassName_myfunc
(JNIEnv * env, jobject obj, jint code) {
...
}
So you will have to create wrapper functions.
A reasonable approach is to define a class including the Java versions of all your native functions (as either static or instance methods), and invoke them via that class.
To generate C headers from the Java (well, not source but the .class files), you can do:
cd bin/classes
javah com.mycompany.MyClassName com.mycompany.AnotherClassName

How to link crypto shared library in Android JNI

I am writing a wrapper to use some functions of crypto.
I build crypto lib from openssl-android with Android-NDK. Now i have the libcrypto.so that i need, but i donĀ“t know how to link it with my wrapper.
My project tree is like this
(proj root)
|
|->(src)
|->(src)-> com.package
|->(src)-> com.package->NativeCipher.java
|
|->(jni)
|->(jni)->Android.mk
|->(jni)->NativeCipher.c
NativeCipher.java
public class NativeCipher {
static {
System.loadLibrary("crypto");
System.loadLibrary("NativeCipher");
}
public static native byte[] AESEncrypt(byte[] in, byte[] key);
}
NativeCipher.c
#include <string.h>
#include <jni.h>
#include <aes.h>
jbyteArray Java_com_package_NativeCipher_AESEncrypt(JNIEnv* env, jobject this, jbyteArray in, jbyteArray key)
{
// All my code here
}
I need to use the functions of #include that crypto provides.
However, i don't know what to do with the .so files that NDK generates and how to make the Android.mk file to build.
Thanks in advance, i tried to be as specific as posible.
Native libraries go to the libs/armeabi or libs/armeabi-v7a of your Android project. You might want to rename the OpenSSL library though, because the system already has a libcrypto.so. As for your own JNI wrapper, just take the shared library sample from the NDK and modify to use your own files.

Categories

Resources