Error internal linkage but is not defined in JNI WebRTC - c++

I tried to compile WebRTC with my customized function, but I always get the error like this:
In file included from ../../sdk/android/src/jni/pc/octon_frame_encryptor.cc:5:
gen/sdk/android/generated_peerconnection_jni/OctonFrameEncryptor_jni.h:41:14: error: function 'webrtc::jni::JNI_OctonFrameEncryptor_GetOctonFrameEncryptor' has internal linkage but is not defined [-Werror,-Wundefined-internal]
static jlong JNI_OctonFrameEncryptor_GetOctonFrameEncryptor(JNIEnv* env, const
^
gen/sdk/android/generated_peerconnection_jni/OctonFrameEncryptor_jni.h:48:10: note: used here
return JNI_OctonFrameEncryptor_GetOctonFrameEncryptor(env,
^
1 error generated.
I don't know what is wrong with my function, here is my octon_frame_encryptor.cc inside src/jni/pc. For JNI_OctonFrameEncryptor_SetKey it seems that it does not throw compiling error.
#include "api/crypto/octon_frame_encryptor.h"
#include <vector>
#include "sdk/android/generated_peerconnection_jni/OctonFrameEncryptor_jni.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
static jlong JNI_OctonFrameEncryptor_GetOctonFrameEncryptor(
JNIEnv* jni,
const base::android::JavaParamRef<jobject>& thiz,
const base::android::JavaParamRef<jintArray>& key_bytes) {
jintArray key_bytes_array = key_bytes.obj();
jsize size = jni->GetArrayLength(key_bytes_array);
jint* key_bytes_ptr = jni->GetIntArrayElements(key_bytes_array, 0);
std::vector<uint8_t> key_bytes_vector(key_bytes_ptr, key_bytes_ptr + size);
return jlongFromPointer(new OctonFrameEncryptor(key_bytes_vector));
}
static void JNI_OctonFrameEncryptor_SetKey(
JNIEnv* jni,
const base::android::JavaParamRef<jobject>& thiz,
const base::android::JavaParamRef<jintArray>& key_bytes) {
jintArray key_bytes_array = key_bytes.obj();
jsize size = jni->GetArrayLength(key_bytes_array);
jint* key_bytes_ptr = jni->GetIntArrayElements(key_bytes_array, 0);
std::vector<uint8_t> key_bytes_vector(key_bytes_ptr, key_bytes_ptr + size);
OctonFrameEncryptor* encryptor =
reinterpret_cast<OctonFrameEncryptor*>(thiz.obj());
encryptor->SetKey(key_bytes_vector);
}
} // namespace jni
} // namespace webrtc

Related

JNI Error : java.lang.NoSuchMethodError: no static method

Error Message : Pending exception java.lang.NoSuchMethodError thrown by 'void com.exampleTest.NDKT.I(android.app.Activity):-2'
java.lang.NoSuchMethodError: no static method "Lcom/exampleTest/NDKT;.PN()Ljava/lang/String;"
I should try ndk c++ call java method because i want you java method thought android package name know
i tried below
java call method String -> void change
=> c++ : jmethodID jMethod = pE->GetStaticMethodID(jClass, "GO", "()V");
java code "this" -> "MainActivity.this"
- Java code
CallNDK class{
public static void initialize(final Activity a,final SIMECB cb) {
System.loadLibrary("simpleinit");
_CB = cb;
_INSTANCE = new CallNDK();
new Thread(new Runnable() {
public void run() {
_INSTANCE.I(a);
}
}).start();
}
}
==> initialize () -> Activity = MainActivity.this
- NDK
CallNDK.cpp
static string mPN; //Packege Name
#ifdef __ANDROID__
void CallNDK::I(JNIEnv* pE, jobject pA){
// Package Name Method call
CHECK::PN(pE, mPN);
}
CHECK.h
#ifndef CHECK_H_
#define CHECK_H_
#ifdef __ANDROID__
#include <jni.h>
#endif
using namespace std;
class CHECK {
public:
#ifdef __ANDROID__
static void PN(
JNIEnv* pE,
string& pO);
#endif
};
#endif
CHECK.cpp
#include "CHECK.h"
#ifdef __ANDROID__
#include <jni.h>
#endif
using namespace std;
#ifdef __ANDROID__
void CHECK::PN(JNIEnv* pE, string& pO){
jclass classes = pE->FindClass("com/exampleTest/NDKT");
jmethodID jMethod = pE->GetMethodID(classes, "SimpleMethod", ()Ljava/lang/String;");
if(!jMethod) {
CALLUtil::LOG("class loader method access");
return;
}
jstring jsResult = (jstring)pE->CallStaticObjectMethod(jClass, jMethod);
const char* cResult = pE->GetStringUTFChars(jsResult, NULL);
std::string sResult(cResult);
pO = sResult;
}
- NDK of call java class code
enter code here
NDKT Class {
private static int _MAX_TRY_INVOKE_COUNT = 5;
public static String SimpleMethod(Activity a){
for(int i = 0; i < _MAX_TRY_INVOKE_COUNT; i++) {
try {
return a.getApplicationContext().getPackageName();
} catch (Exception e) {
try { Thread.sleep(50); } catch (Exception e2) { }
}
}
return ""
}
}
Error
JNI DETECTED ERROR IN APPLICATION:
JNI FindClass called with pending exception 'java.lang.NoSuchMethodError' thrown in void com.exampleTest.CallNDK.I(android.app.Activity):-2 in call to FindClass from void com.exampleText.CallNDK.I(android.app.Activity)
Pending exception java.lang.NoSuchMethodError thrown by 'void com.exampleTest.NDKT.I(android.app.Activity):-2'
java.lang.NoSuchMethodError: no static method "Lcom/exampleTest/NDKT;.PN()Ljava/lang/String;"

how to declare c# dll functions dynamically in c++ builder

i tried the code shown below to call a c# dll function (COM) but when i do that i get the errors below "Invalid use of namespace 'MaxElementFn'"
My guess is that maybe i am calling the c# dll function incorrectly in c++ builder. any suggestion will be greatly appreciated. thank you in advance.
#include <Windows.h>
#include <cstdio>
using MaxElementFn = int(__stdcall *) (int a, int b);
int main()
{
HMODULE mod = LoadLibraryA("ExportedCodeSolution.dll");
MaxElementFn maxElement = reinterpret_cast<MaxElementFn>(GetProcAddress(mod, "maxElement"));
std::printf("max: %d\n", maxElement(1, 2));
}
[BCC32 Error] Unit1.cpp(145): E2070 Invalid use of namespace 'MaxElementFn'
[BCC32 Error] Unit1.cpp(151): E2451 Undefined symbol 'MaxElementFn'
these are the errors i am getting
// helper template
template<typename T>
bool GetFuncPointer(HMODULE module, const char* name, T& ptr)
{
ptr = (T)GetProcAddress(module, name);
if(!ptr) std::printf("function not found in dll: %s\n", name);
return ptr != nullptr;
}
// declare func pointer
int (__stdcall * maxElement) (int, int) = nullptr;
int main()
{
HMODULE mod = LoadLibraryA("ExportedCodeSolution.dll");
// make sure we actually have the function before calling
if(GetFuncPointer(mod, "maxElement", maxElement))
{
std::printf("max: %d\n", maxElement(1, 2));
}
return 0;
}

Unresolved external symbol when using std::wstring

I declared the the following class:
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
namespace util
{
class FileReader
{
public:
FileReader();
~FileReader();
bool open(const std::wstring& name);
void close();
bool read(std::vector<char>& buf, __int64 startFrom, int size);
__int64 size() const;
private:
FILE* m_file;
std::wstring m_name;
__int64 m_size;
};
}
And its implementation:
#include "FileReader.hpp"
namespace util
{
bool FileReader::open(const std::wstring& name)
{
if (!name.empty() && (m_name != name))
{
close();
if (_wfopen_s(&m_file, name.c_str(), L"rb") == 0)
{
m_name = name;
// Get the file size
_fseeki64(m_file, 0, SEEK_END);
m_size = _ftelli64(m_file);
rewind(m_file);
}
else
{
m_file = NULL;
}
}
return (m_file != NULL);
}
// ....
}
in a seperate library and use it like this:
FileTransfer.cpp
#include <util/FileReader.hpp>
// .....
if (!m_fileReader.open(m_localFileName)) // std::wstring m_localFileName;
{
::MessageBoxA(NULL, "Failed to open file", "Error", MB_ICONERROR);
stopFileTransmission();
return;
}
in another project. Both projects compile successfully, but the FileTransfer.obj fails to link:
Error 2 error LNK2019: unresolved external symbol "public: bool
__thiscall util::FileReader::open(class std::basic_string,class
std::allocator > const &)"
(?open#FileReader#util##QAE_NABV?$basic_string#GU?$char_traits#G#std##V?$allocator#G#2##std###Z)
referenced in function
__catch$?onRequestDirClicked#FileTransferWindow##AAEXXZ$0 C:\Users\x\Documents\dev\Server\FileTransfer.obj Server
I remember it was working when I used std::string, so I assume it has something todo with std::wstring.
Any idea what could be the issue?
It seems, the problem was that the two projects had different values for the setting
Treat wchar_t as built-in type
Setting it to No (/Zc:wchar_t-) for both projects, solved the linker error. I still don't really know what the consequences will be though.
try using extern "C" to declare the open function.

c++: g++: extern "C" function definition?

I am having trouble creatiung a C++ library with a extern "C" function interface. I have the following header
#ifndef MYUTILITIES_H_
#define MYUTILITIES_H_
namespace MYUtilities {
static std::string UpperCase(std::string);
class MyException: public std::exception {
public:
MyException(std::string ss)
: s(ss) {
}
~MyException() throw () {
} // Updated
std::string s;
const char* what() const throw () {
return s.c_str();
}
};
} /* namespace ITGUtilities */
/*
* General utility functions
*/
extern "C" const char * UpperCase(const char *);
#endif /* MYUTILITIES_H_ */
source file
#include "ITGUtilities.h"
namespace ITGUtilities {
const char * UpperCase(const char * str) {
std::string tmp = str;
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
return tmp.c_str();
}
std::string UpperCase(std::string str) {
std::string tmp = str;
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
return tmp;
}
} // namespace ITGUtilities
In the .cpp source file I have tried defining the char *UpperCase(const char *) routine inside and outside of the namespace. In either case nothing that tries to use this library can find a reference for the extern function.
I have seen an example in the MySQL C++ cppcon/driver.h header where the extern definition is in the header but outside the namespace.
extern "C"
{
CPPCONN_PUBLIC_FUNC sql::Driver * get_driver_instance();
/* If dynamic loading is disabled in a driver then this function works just like get_driver_instance() */
CPPCONN_PUBLIC_FUNC sql::Driver * get_driver_instance_by_name(const char * const clientlib);
}
I just don't know what magic I should be using here.
help?
Use the curly braces to define your external C function:
extern "C"
{
UpperCase(const char *);
}
First of all, do not define extern functions in namespaces, it makes no sense. To check what was the name of generated function in object file, use utility called nm (on *nix). It should tell you of the name was mangled or not.
In your case, I assume the problem is that you have an overload with a different name and C++ linkage. I suggest you name your C-linkage function differently.

Comparing an error code enum with std::error_code

I'm using the C++11 system_error error code library to create a custom error class for a library I'm making. I've done this before with boost::error_code, but I can't quite it get it working with std::error_code. I'm using GCC 4.6.
Basically, I've laid out all the boilerplate code to create an error class, an error_category, and the conversion routines in the STD namespace to convert my custom enums into an std::error_code object:
namespace mylib
{
namespace errc {
enum my_error
{
failed = 0
};
inline const char* error_message(int c)
{
static const char* err_msg[] =
{
"Failed",
};
assert(c < sizeof(err_msg) / sizeof(err_msg[0]));
return err_msg[c];
}
class my_error_category : public std::error_category
{
public:
my_error_category()
{ }
std::string message(int c) const
{
return error_message(c);
}
const char* name() const { return "My Error Category"; }
const static error_category& get()
{
const static my_error_category category_const;
return category_const;
}
};
} // end namespace errc
} // end namespace mylib
namespace std {
inline error_code make_error_code(mylib::errc::my_error e)
{
return error_code(static_cast<int>(e), mylib::errc::my_error_category::get());
}
template<>
struct is_error_code_enum<mylib::errc::my_error>
: std::true_type
{ };
The problem is, implicit conversion between my error code enums and std::error_code objects doesn't seem to be working, so I can't for example try and compare an instance of std::error_code with enum literals:
int main()
{
std::error_code ec1 = std::make_error_code(mylib::errc::failed); // works
std::error_code ec2 = mylib::errc::failed; // doesn't compile
bool result = (ec2 == mylib::errc::failed); // doesn't compile
}
The expression ec2 == mylib::errc::failed won't compile - I have to say ec2 == std::make_error_code(mylib::errc::failed).
The error the compiler emits is:
In file included from test6.cc:3:0:
/usr/include/c++/4.6/system_error: In constructor ‘std::error_code::error_code(_ErrorCodeEnum, typename std::enable_if<std::is_error_code_enum<_ErrorCodeEnum>::value>::type*) [with _ErrorCodeEnum = mylib::errc::my_error, typename std::enable_if<std::is_error_code_enum<_ErrorCodeEnum>::value>::type = void]’:
test6.cc:70:37: instantiated from here
/usr/include/c++/4.6/system_error:127:9: error: cannot convert ‘mylib::errc::my_error’ to ‘std::errc’ for argument ‘1’ to ‘std::error_code std::make_error_code(std::errc)’
And here's an Ideone link.
So, why isn't this working? Do I need additional boilerplate code to enable mylib::errc::my_error enums to be implicitly convertible to std::error_code? I thought that the specialization of std::make_error_code takes care of that?
You have to move error_code make_error_code(mylib::errc::my_error e) function from std to your error namespace (mylib::errc). Please check http://ideone.com/eSfee.