UnsatisfiedLinkError about Static Member initialized in class in ndk r15 - c++

I encounter a problem about UnsatisfiedLinkError.
My code is :
class ClassA
{
public:
static const int MY_ENUM_1 = 0;
};
I use Android Studio build my code to .a.
And then I write .so for link the interface of my lib via JNI.
I build the project successfully. But it occur an error about this while run-time,
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN12LaChenEngine14GraphicsSystem22VertexBufferAccessList12DYNAMIC_DRAWE
LaChenEngine is the namespace.
GraphicsSystem is the namespace in LaChenEngine.
VertexBufferAccessList is my class for declaring all enum.
DYNAMIC_DRAW is one of enum in class VertexBufferAccessList.
Is this problem about version in ndk?
By the way, I develop my library on Windows Platform.

One possible cause is that one project defines a extern "C" function, and the other assumes that it is a C++ function.
More info: https://stackoverflow.com/a/1041880/755804
Another guess: check if that function is there in your .so, and if not, find out where it is.
In general, how I would approach such linkage problem is: I would start with a hello-jni application, adding one feature at a time (another library, C++ functions, C++ functions in name spaces, etc.)

I test many version of ndk, it still happen again and angin.
So I decide to change the code like this :
//.h
class ClassA
{
public:
static const int MY_ENUM_1;
};
//.cpp
const int ClassA::MY_ENUM_1 = 0;
And then, it work.
Thanks for all helps.

Related

Using a c++ builder application with an external dll

I'm trying to use an external dll in my c++ builder application. The dll (let.s call it X.dll) was created with Qt Creator (using MingW 32 bit compiler, tried gcc as well )
and consists of a single functon to keep things simple (besides X.dll, an import library X.a is also created).
The dll header (Dll_lib.h) is basically just
__declspec(dllexport) Dll_method(float *p, int n);
If I create a simple Qt application, add the dll header to it and link it to the dll import library X.a, everythink works as expected.
However, when I try to use the dll in my c++ builder application, I get an "unresolved external _Dll_method referenced from ..." error.
The part of my c++ builder app that references the dll looks like
#include "lib\Dll_lib.h"
#pragma comment(lib, "X.lib")
__declspec(dllimport) Dll_method(float *p, int n);
.....
X.lib was created directly from the dll using the implib tool that comes bundled with c++ builder. I also tried to create X.lib from X.a using coff2omf tool but nothing worked and I always get the same error message.
C++ environments have a habit of name mangling to support overloads, different arguments with the same name, like:
int use(int x, char y); // mangles to something like use__Int__Chr.
int use(double x); // mangles to something like use__Dbl.
This allows the correct one to be linked depending on the arguments.
You may need to wrap it inside extern "C" to get it to not mangle the name, something like:
extern "C" {
__declspec(dllimport) Dll_method(float *p, int n);
}
That's assuming you're creating it without name mangling and using it from something that assumes it is mangled. If it's mangled on both sides, you'll probably have to create and use it with extern "C" since there's no guarantee different compilers will mangle with the same rules.
As an aside, you should be able to examine the object files or DLLs created by your toolchain, to ascertain what the function is called where it's defined and also what it's expected to be by the caller. Under Linux, I'd use something like nm, I'm not sure what the equivalent is for Windows.

Referring to an object from custom library gives error: "pointer to incomplete class type is not allowed"

So in my Visual Studio solution I'm making a library and I have two Visual Studio projects, one for the library and one for the sandbox. In the library I'm trying to use forward declarations to create a class. What I'm simply doing in this example is creating a header file for my class, declaring std::string with the following forward declaration and creating a member pointer with that class.
Library project:
ClassFromLibrary.h
#pragma once
namespace std {
class string;
}
class ClassFromLibrary {
public:
ClassFromLibrary();
~ClassFromLibrary();
std::string* forwardDeclaredString;
};
ClassFromLibrary.cpp
#include "ClassFromLibrary.h"
#include <string>
ClassFromLibrary::ClassFromLibrary()
: forwardDeclaredString(new std::string("Hello, world!"))
{
}
ClassFromLibrary::~ClassFromLibrary()
{
}
Sandbox project
main.cpp
#include <Library/ClassFromLibrary.h>
#include <iostream>
int main()
{
ClassFromLibrary test;
std::cout <<
*test.forwardDeclaredString //Root of the problem
<< std::endl;
std::cin.get();
}
The problem
As I said earlier, the library project compiles perfectly. However, the error which I mentioned in the title shows up when the forward declared member variable is referenced in any file from the sandbox project. I have a larger project where I get the same error, and the reason I want to achieve this is because I am using other external libraries within my library project, and when I create applications with it I don't want to have to put all the library include directories in the project properties, only the one for my library.
Thanks in advance!
You know that putting names in namespace std makes program ill-formed (except for some cases?)? Well, know you know why. The bug you have is a symptom of undefined behavior.
In my test, the way you declared your forward declaration in std is not how it is actually declared in string header. Yet it's a same name, so now you have name conflict (you have it as soon as you include iostream, which includes string. This is what my compiler is telling me when I am try compile your code:
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/bits/basic_string.h:6628:17:
error: reference to 'string' is ambiguous
struct hash<string>
This is different from the error you put in the question, but since the behavior is undefined, anything can happen.

LoadLibrary fails with error 203: The system could not find the environment option that was entered

I created a c# class library. I want to load this .dll in my win32 console application, because I have exported one function from the c# class library to unmanaged code and I don't know of any other way to call that function now.
But LoadLibraryA is giving me that error, what can it mean? Googling didn't help me at all.
Used this to export the function to unmanaged:
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports#TOC-C-:
EDIT: Here is the code, sorry I didn't include it at first because it's as barebones as it gets:
using System;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
namespace ManagedLibrary
{
public class Test
{
[DllExport(CallingConvention = CallingConvention.Cdecl)]
public static void test()
{
Console.WriteLine("HI");
}
}
}
Looks like the unmanaged exports nuget tool doesn't work for me, the .dll loading errors were mostly obscure and unrelated as it seems (although I did switch to my home computer now)
After I have manually added the exports IL statement as described here:How do you export a method in a CIL DLL so that a native program can call it? I was able to call the C# code just fine.

Exporting constants from a DLL

I'm working with VC9 on Windows.
I have a library (lets call it libfoo) which is made of the following files ("include guards" and "#include" directives omited for clarity's sake):
// foo.hpp
class Foo
{
public:
static const std::string SOME_CONST;
};
And:
// foo.cpp
#include "foo.hpp"
const std::string Foo::SOME_CONST = "hello";
Foo::SOME_CONST is exported using a .def file.
The library compiles fine: a libfoo.lib file and a libfoo.dll file are generated.
I used this library in a sample program, like:
// main.cpp
#include <foo.hpp>
int main()
{
std::cout << Foo::SOME_CONST << std::endl; // std::bad_alloc here
return EXIT_SUCCESS;
}
A std::bad_alloc is thrown whenever I attempt to use Foo::SOME_CONST.
This only happens if I link dynamically to libfoo. Linking statically results in a perfectly working program.
What could possibly be going on here ? Is it legal to export a std::string constant that way ?
Check if dll actually does dynamic initialization, because it might not, standard has no requirements for dynamic libraries. Wrapping globals in static functions can be the solution.
Use __declspec(dllexport) and __declspec(dllimport). Stop worrying about .def files and all of that rubbish- let the compiler do the work.
Are the library and the main application linking to the same version of the standard library and/or CRT and/or MFC, with exactly the same settings? I've seen allocation issues when using different versions of the CRT, and also fought bugs caused by different iterator debugging settings between a library and its including application.

[windows] back linking

There is shared class. Declarator is in shared header, implementation is in main program. Main program load DLL and exec some function from it, function create object of shared class.
Test code:
shared_header.h:
#include<stdio.h>
class sharedClass{
public:
sharedClass();
};
plugin.cpp -> libplugin.dll
#include"shared_header.h"
extern "C"
void loader(){
printf("Plugin is loaded!\n");
new sharedClass;
}
base.cpp -> base.exe
#include"shared_header.h"
sharedClass::sharedClass(){
printf("Shared class is loaded!\n");
}
int main(){
/*
some actions to load libplugin.dll and exec function loader
*/
return 0;}
So, I want see
Plugin is loaded!
Shared class is loaded!
And it works on Linux. But while I link libplugin.dll on Windows I have error "undefined refernce to sharedClass::sharedClass()". How I need link program and plugin to use this way?
PS. Mingw, stable version.
PPS. I'm so sorry for my terrible English.
Windows DLLs are non exactly the same thing as UNIX/Linux shared objects.
On Windows, DLLs must be fully linked and have all their references defined. Therefore, as your file plugin.cpp references the sharedClass constructor, the linker will require that this constructor is defined and available to create the DLL. It is not possible to provide it in the executable that loads the DLL.
On UNIX/Linux, shared objects behave differently. Their dependencies are solved when they are loaded by the executable. Therefore, the executable can provide some of the functions needed by the shared object.