Вызов функции JNI C в другом исходном файле - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь вызвать функцию C foo () из файла JNI native-lib.cpp.foo () объявлен в foo.h и определен в foo.c.В native-lib.cpp уже включен «foo.h», поэтому Android Studio, похоже, распознает, что функция существует, но при сборке я получаю следующую ошибку:

error: undefined reference to 'foo(unsigned char const*, unsigned int*, int)'

foo () объявляется как таковаяв foo.h:

void foo(const unsigned char key[], unsigned int w[], int keysize);

foo () вызывается в native-lib.cpp следующим образом:

static unsigned char byteArray[32];
unsigned int intArray[64];
foo(byteArray, intArray, 256);

Я что-то пропустил?Почему я получаю сообщение об ошибке?

Я также замечаю, что когда я открываю свой foo.c, Android Studio сообщает мне: «Этот файл не является частью проекта. Пожалуйста, включите его в соответствующий файл сборки (сборка»)..gradle, CMakeLists.txt или Android.mk и т. д.) и синхронизировать проект. "Как мне это сделать?

1 Ответ

0 голосов
/ 05 декабря 2018

Вероятная проблема заключается в том, что ваша функция foo() распознается компоновщиком как функция C++, а не как функция C.

Поскольку функции C++ могут быть перегружены, компилятор C ++ "искажает" имя, чтобы у компоновщика был уникальный ключ к функции.Любой модуль C ++, который встречает foo.h, предположит, что эта функция является функцией C ++, поэтому изменение имени будет выполнено для имени функции.

Например, возможно, искаженное имя выглядит примерно так в скомпилированном объектном коде:

foo@ucharp@uintp@int

(у каждого бренда компилятора C ++ будет своя собственная схема именования).

С другой стороны, когда компилятор C встречает foo.h, скомпилированный объектный код выдает символ, представляющий собой "неупорядоченное" имя foo, более или менее это:

foo или _foo

Так что теперь во время компоновки, так как вы вызвали функцию foo из кода C ++, компоновщик попытается найти искаженную версию, и поскольку C ++ отсутствуетФункция с именем foo, вы получаете ошибку компоновщика.

Таким образом, ваш заголовок foo.h или его использование должны быть умными и работать для модулей C и C ++.где модули C ++ знают, что foo относится к функции C и, следовательно, не будут искажать имя.


Один из способов сделать это - изменить foo.h на следующее:

#ifdef __cplusplus
extern "C" {
#endif

    void foo(const unsigned char key[], unsigned int w[], int keysize);

#ifdef __cplusplus
}
#endif

Таким образом, когда заголовок C компилятор видит, __cplusplusне существуетДля модулей C ++ определяется __cplusplus, и, таким образом, extern "C" вступает в силу, поэтому модули C ++ распознают foo() как C функцию.

Если вы не можете изменить foo.hзатем вы можете окружить его extern "C" в ваших модулях C ++:

extern "C" {
  #include <foo.h>
}

См. это для получения дополнительной информации о __cplusplus

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...