我嘗試開發一個Android應用程序。我已經設法使用NDK實現一個相當小的C++函數。但是現在我想使用我在Google Docs上找到的一個非常大的C++庫。 當我現在嘗試用NDK的構建工具,構建它,我得到這個錯誤在Cygwin的控制檯:NDK對{extern「C」函數}的未定義引用?
Compile++ thumb : ndkfoo <= subspace.cpp
Compile++ thumb : ndkfoo <= classifier.cpp
Compile++ thumb : ndkfoo <= eigen.cpp
Compile++ thumb : ndkfoo <= image.cpp
Compile++ thumb : ndkfoo <= imageio.cpp
Compile++ thumb : ndkfoo <= local.cpp
Compile++ thumb : ndkfoo <= matrix.cpp
Compile++ thumb : ndkfoo <= sample.cpp
SharedLibrary : libndkfoo.so
./obj/local/armeabi/objs/ndkfoo/eigen.o: In function `LibSubspace::geneigen(doub
le*, double*, int, double*, int, bool)':
U:\workspace\test/jni/eigen.cpp:91: undefined reference to `ilaenv_'
U:\workspace\test/jni/eigen.cpp:96: undefined reference to `dsygv_'
U:\workspace\test/jni/eigen.cpp:128: undefined reference to `dggev_'
./obj/local/armeabi/objs/ndkfoo/eigen.o: In function `LibSubspace::eigen(double*
, double*, double*, int, bool)':
U:\workspace\test/jni/eigen.cpp:55: undefined reference to `ilaenv_'
U:\workspace\test/jni/eigen.cpp:58: undefined reference to `dsyev_'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/libndkfoo.so] Error 1
這個函數的代碼是如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <assert.h>
#include <string.h>
#include "eigen.h"
extern "C" int ilaenv_(int *ispec, const char *name__, const char *opts,
int *n1, int *n2, int *n3, int *n4, int name_len, int opts_len);
extern "C" int dsyev_(const char *jobz, const char *uplo, int *n, double *a,
int *lda, double *w, double *work, int *lwork,
int *info);
extern "C" int dsygv_(int *itype, const char *jobz, const char *uplo, int *
n, double *a, int *lda, double *b, int *ldb,
double *w, double *work, int *lwork, int *info);
extern "C" int dggev_(const char *jobvl, const char *jobvr, int *n, double *
a, int *lda, double *b, int *ldb, double *alphar,
double *alphai, double *beta, double *vl, int *ldvl,
double *vr, int *ldvr, double *work, int *lwork,
int *info);
namespace LibSubspace {
int eigen(double* A, double* V, double* E, int n, bool verbose) {
int info;
int ispec = 1;
int lwork;
lwork = (ilaenv_(&ispec,"DSYEV","U",&n,&n,&n,&n,5,1)+2)*n;
double *work = (double *)malloc(lwork*sizeof(double));
memcpy(V,A,n*n*sizeof(double));
dsyev_("V","U",&n,V,&n,E,work,&lwork,&info);
free(work);
//check the return value
if(info!=0) {
if(verbose) {
printf("Error computing eigenvectors: ");
if(info>0) {
printf("Algorithm failed to converge\n");
} else if(info<0) {
printf("Illegal argument\n");
} else {
printf("Unknown error\n");
}
}
return 0;
}
return 1;
}
int geneigen(double *A, double *B, int n, double *W, int algorithm,
bool verbose) {
//getting the optimal lwork
int ispec = 1;
int lwork;
int info;
switch(algorithm) {
case EIGEN_CHOL:
{
//computing eigenvectors
lwork = (ilaenv_(&ispec,"DSYGV","U",&n,&n,&n,&n,5,1)+2)*n;
double *work = (double *)malloc(lwork*sizeof(double));
int problemType = 1;
char job = 'V';
char uplo = 'U';
dsygv_(&problemType,&job,&uplo,&n,A,&n,B,&n,W,work,&lwork,&info);
free(work);
//check the return value
if(info!=0) {
if(verbose) {
printf("Error computing eigenvectors: ");
if(info>n) {
printf("Matrix B is not positive definite\n");
} else if(info<=n) {
printf("The problem failed to converge\n");
} else if(info<0) {
printf("Illegal argument\n");
} else {
printf("Unknown error\n");
}
}
return 0;
}
}
break;
case EIGEN_QZ:
{
//more general algorithm
double *alphar = (double *)malloc(n*sizeof(double));
double *alphai = (double *)malloc(n*sizeof(double));
double *beta = (double *)malloc(n*sizeof(double));
double *VR = (double *)malloc(n*n*sizeof(double));
lwork = 8*n;
double *work = (double *)malloc(lwork*sizeof(double));
dggev_("N","V",&n,A,&n,B,&n,alphar,alphai,beta,
NULL,&n,VR,&n,work,&lwork,&info);
//eigenvalues
for(long i=0;i<n;i++) {
if(beta[i]!=0) {
W[i] = alphar[i]/beta[i];
} else W[i] = 0;
}
//eigenvectors
for(long i=0;i<n;i++) {
for(long j=0;j<n;j++) {
A[i*n+j] = VR[i*n+j];
}
}
free(alphar);
free(alphai);
free(beta);
free(VR);
free(work);
if(info!=0) {
printf("Error computing eigenvectors: ");
if(info<0) {
printf("Illegal argument\n");
} else if(info<=n) {
printf("QZ iteration failed\n");
} else {
printf("Unknown error\n");
}
return 0;
}
}
break;
}
return 1;
}
} //namespace
不幸的是我是絕對不明白爲什麼發生這些錯誤。我對C++並不熟悉,這就是爲什麼我想使用NDK,希望不必更改現有庫的任何內容。
這些是鏈接器錯誤,而不是編譯器錯誤。您需要爲鏈接器命令指定相關的庫。 – 2012-01-09 14:04:42
我有沒有在Android.mk中做到這一點?我認爲ndk-build工具會自動完成鏈接:( – Matthias 2012-01-09 14:12:03
那麼,無論你從哪裏獲得這四個函數,都必須在鏈接時提供,但是你可以檢查實際的鏈接器調用,看看是否所有東西都是如你所期望的那樣,並且仔細檢查函數聲明,如果你也是爲那些來自庫的人設計的。 – 2012-01-09 14:18:24