Xamarin: use NDK-built .so - build

I made two simple functions (set and return an int) on eclipse (Android project) in C. I used ndk-build to produce a .so. How can i use this .so on Xamarin and consume those two functions on my Xamarin.Android project?
Thanks!

Let’s assume we have a shared library called MyTest.so and we want to use it in the Xamarin.Android project. The MyTest.so consists of a function
int MyTest_GetValue();
Now, we need to use this function on Xamarin.Android project. Here are the steps so as to succeed:
Step 1: Create a new folder inside the Xamarin.Android project called lib and sub-folder armeabi. Copied my .so library to be used inside the armeabi folder as stated here
Step 2: Set the properties of the library.so (imported library) Build action to "AndroidNativeLibrary" and Copy to output to "Always Copy".
Step 3: (Working in Xamarin.Android Class eg: MainActivity.cs)
Include the namespace InteropServices by “using System.Runtime.InteropServices;”
Use the standard DllImport in the project to import the native library as below:
[DllImport("MyTest.so")]
public extern static int MyTest_GetValue();// with exact Functtion Name, Type & Params in the .so Lib.
Step 4: Consume the function above (MyTest_GetValue()) in the application.
For Example:
int value= MyTest_GetValue();
Console.Writeline(value.ToString());
Mission Accomplished! :D

Related

How to compile a static library with Codelite 11.0.0?

I would like to compile a static library out of all the functions I have written for a C++ project. I am using CodeLite 11.0.0 on Ubuntu 16.04, configured to use GCC as compiler.
I have followed the instructions in CodeLite's tutorial, according to which this should be possible, and changed the project type from Executable to Static Library.
After running the project (CTRL+F5 command), I expected to find a .a file in the /Debug folder, either along with, or in place of the executable file. All I could find, though, was the executable and a number of .o and .o.d files. The same I was finding when the project was set to Executable.
I tried to close and reopen CodeLite, but it did not help. I can't find any official/unofficial example of how to build a static library with CodeLite.
Does anyone know how to set-up CodeLite to produce a .a static library file?
As you've probably discovered, CodeLite allows you to change the type of a
project in the drop-down menu from Settings -> General -> Project type.
Doing so, however, does not change the name of the project target. So, if
you started off your project as an executable myprog - from which, say, the
Debug build generated ./Debug/myprog under the project folder - then
you change the project type to static library and rebuild it, the Debug
build will still generate ./Debug/myprog, but that file will now in fact
be a static library, lacking the customary lib-prefix and .a extension.
To give the output file a conventional static library name -
libmyprog.a - you need to go back into Settings -> General and
change Output File from:
$(IntermediateDirectory)/$(ProjectName)
to:
$(IntermediateDirectory)/lib$(ProjectName).a
Then rebuild the project and it will output a target that is a static
library and looks like one.
Of course, you must make the same changes to the project settings in both
the Debug and Release configurations if you want them both to produce
targets with the same file type and file name.
However...
If this way of converting a program project to a static library project does not
seem very slick, that could be because it is a conversion of very little use.
The static library produced after the conversion will contain exactly the same object
files that the program was built from, including the object file that defines
the main function of the original program. Let's suppose that object file
is main.o, and that it defines 0 or more other functions that the linker can see.
Any other program, newprog, that is linked with the static library must provide
its own main function in a different object file, so in any such linkage one of
two things must happen:-
The linkage of newprog does not need any function defined in libmyprog.a(main.o),
so libmyprog.a(main.o) is not linked and might as well not exist.
The linkage of newprog does need some function, foo, defined in libmyprog.a(main.o),
so libmyprog.a(main.o) is linked; then as well as the definition of foo, the
program links duplicate definitions of main - its own definition plus the
one in libmyprog.a(main.o). Duplicate definitions are an error, so the linkage fails.
Putting a definition of some program's main function into a member of a static
library is pointless, because if that member is ever needed in the linkage of another
program then its linkage will fail.
So converting your program project to a static library project calls for some
refactoring prior to the conversion:-
If any function that you want in the static library is defined in the same source
file as main, then you need to take it out of that source file and define it
is a different one.
After that, remove the source file that defines main from the project.
Lastly, convert and rebuild the project.
You have to do that refactoring to extract from your original program source code
a bunch of source files that are suitable for building into a static library.
Assuming you've done that, the straightforward way to create a static library with
CodeLite is to create a project for that purpose and in the New Project Wizard
choose Library -> Static Library as the project type instead of some kind
of executable.
Then just add either new or existing source files to the static library project
until it contains definitions of all the functions you want the library to
provide. Build, test, debug, edit... until done.

execute the global variable generation part of a library in an executable project

My application is consists of two projects which one of them create the executable file and the other generates the library that executable is going to use. I have tested the library before using some Main test. There are some global variable definitions in the library project which should be executed (to create some default options) before my executable project started to work. For example in my library project, I have code like this:
const ifxFactoryProductInitializerNew<ifxComplexResultContainer, ifxResultContainer<1, ifxComplexVector3f> > fp_r1("1");
const ifxFactoryProductInitializerNew<ifxComplexResultContainer, ifxResultContainer<2, ifxComplexVector3f> > fp_r2("2");
const ifxFactoryProductInitializerNew<ifxComplexResultContainer, ifxResultContainer<3, ifxComplexVector3f> > fp_r3("3");
How can I use this library while the global part of it executes before my executable projects run?
As I look for it, it is not possible.
I have to put the global definitions in a function and call that function in the beginning of the executable project.

How to bind static library in a dynamic one in Code::Blocks

I have this static(.a/.lib) library which I wanted to bind in my dynamic(.dll).
Lets say the static library is libColors.a and the dynamic is SWC.dll.
Now I already change the libColors.a project properties to make a static library--build it--and I haven't found any .dll created, only the .o and .a files which is expected. I switched to my SWC.dll project and change its properties to make a dynamic library and check the box to create also a .a file--link the libColors.a--build it--and the .dll file is created. (also note that I put __declspec(import/export) specification on its classes)
Now I want this SWC.dll to use in an executable file. However, when I include only the SWC.h file in the executable, it gets tons of undefined references. Seems there's a problem here since I didn't call any functions on SWC.h. So, I add on my .exe build options the SWC.a, now it builds with no error. But when I run it, it says I needed the Colors.dll? What do I miss?
You can use tools like objdump, CFF Explorer or Dependency Walker to view the import table of the PE-COFF executable in question.
The likely explanation is that the way your Colors project is compiled isn't really a static library. You can check this by inspecting both SWC.dll and your test executable's import table. Chances are that you'll find an import entry from Colors.dll in one of them and what function's it's trying to import.
Check the data and functions declared in Color.h and make sure they're not decorated with __declspec() anywhere. If the functions in Color.h preprocesses into something like __declspec(dllimport) in 'SWC' this can cause the problem you're seeing.

Linker error - linking two "application" type projects in order to use Google Test

I am trying to test a function with Google Test.
It seems that everything is set up correctly, and it builds and executes fine without gtest... (There is a bit of complexity in the code, so I cannot list all the source files here, but without adding gtest, the files are linking properly, and running as they should).
It is an application type project. It has a number of library dependencies... irrelevant.
The test project is added as a separate project to the solution. It has the tested project as a dependency. The .h file of the test project only points to the gtest... The .cpp (not main, which is the standard InitGoogleTest main) adds its own header file, the header file of the tested project, and has the test shown below.
There is a TestedProject.lib created automatically, when the project builds, even though it is an application. I have added TestedProject.lib as a library dependency to the TestProject (in Link).
Class x
{
public:
x(){} // I didn't really need this, I only added the class so I have access to
~x(){}; // non-class methods with gtest - but it still doesn't work
bool myFunction(std::string a, double b, bool c);
};
implementation:
bool x::myFunction(std::string a, double b, bool c)
{
// implementation
return false;
}
somewhere_else
{
x x_instance;
y = x_instance.myFunction("a", 1, false); // works, all builds, executes, life is great
}
Add unit test:
class TheTest : public ::testing::Test
{
protected:
x x_instance;
};
TEST_F(TheTest, Fail)
{
EXPECT_FALSE(x_instance.myFunction("a", 1, false));
}
Doesn't build. Link error (modified, like the sample code above, with simplified names, I hope I didn't mess up content)
Error 2 error LNK2019: unresolved external symbol
"public: bool __thiscall x::myFunction(class std::basic_string<char,struct std::char_traits<char>,double,bool)"
(?myFunction#x##QAE_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##00000NNNN_N1#Z)
referenced in function "private: virtual void __thiscall TheTest_Fail_Test::TestBody(void)"
(?TestBody#TheTest_Fail_Test##EAEXXZ) C:\path\file.obj
I have done this before - solved link errors - wrote a couple of tests with Google test - but I can't see anything missing.
As a test, I wrote a little
int test(){return 4;}
in the header file, in the class declaration...
and then, replaced the test with
EXPECT_EQ(x.test(), 4);
It worked. Great. But that would mean to have all the tested code in a single file, a cpp or something... which is simply unreasonable. There are a few files in this Application project.
How can I fix this issue ? How can I make Google Test link and test with a class with a header and an implementation file ? When that header/implementation is in a different project, of "Application" type ?
The only similar issue I have found, so far: C++ linking issue on Visual Studio 2008 when crosslinking different projects on same solution
Please, help me find a solution.
There is a another solution, which I prefer because it means you can avoid to change your main project:
Add a "post build action" to the main project in order to create a static library for the exact same source files.
Then you can simply add this dependency to you gtest project.
Each time you'll compile your main project it will build the application AND the static library.
This way you don't have to create a third project and keep configurations synchronized.
Hope it helps.
So I'll have an answer:
I have 2 solutions to my question:
1) Break up the application project in 2 projects, one will become a library, with most of the code; the other will be an application, containing a tiny main() that calls the entry point of the real code (like a parameter parsing method or something).
Then, I can add a unit testing project - to test the lib.
2) Don't break up the project. Add a gtest project, don't create any dependencies. Add the files to test into the gtest project. The gtest project will be a separate executable... with all it needs to be happy. (Advantage: no dependencies for testing)
I prefer the first version.
There is another solution for this.
Just create a new project for Google Test Framework.
(of course, under your existing application solution).
And then, after you make sure all your Google Test Framework setup correctly.
(you can test it under the newly created solution)
Manually include the code your want test (use Add -> Existing Item) from your main project, and then you can test your code without generate additional lib.
The good part of this is that when you test some application which requires DLL from windows, it requires the application uses Multi-threaded Debug DLL.
(in your Project property settings, go to C/C++ -> Code Generation -> Runtime Library see what you got)
And Google Test Framework uses a very different RunTime Library (Multi-threaded Debug (/MTd)).
At the stage of linking, the compiler will cry that it has some difficulty links the generated lib from your application with Multi-Thread DLL and the google framework's lib (which is Multi-threaded).
In this way, you can avoid the dependency problem of both project. (one for /Mtd and one for /Md)

Any way to resolve C4772 errors without having to register DLLs?

I am maintaining a VS2010 project which has a number of cross-referenced COM libraries. I am trying to configure the project in such a way that it is buildable from a random workstation which has VS2010 installed. The workstation could be both 32 and 64 bit, so if I configure project to "register output", the build will fail to build on 32-bit machine, since 64-bit DLL will not be possible to load to call DllRegisterServer.
Here is an example: Typelib from project B references typelib from project A. Project C will reference project B via following statement:
#import "B.tlb"
Since library B references A, when B.tlb is being imported, the compiler tries to load types from A. So, if A is not registered, the compile will fail with:
error C4772: #import referenced a type from a missing type library ...
I tried to open B.tlb using the OleView application, and it's sure as hell only showing right file name for library A reference if it is registered using regsvr32.
So, my question here is: is there any alternative way for library references to resolve themselves properly, without having to register TLBs, just by putting all the files in the same directory somehow, or attaching some sort of manifest? For example, rename the TLB for a library as .tlb or something of that sort.
There is a good option: add path to the .tlb files to VC++ Directories -> Executable Directories
This adds the path to PATH environment variable which will be given to the compiler. According to this: http://msdn.microsoft.com/en-us/library/sce74ah7.aspx all .tlb REFERENCED in imported one are searched only in PATH and LIB.
Try import the referenced A.tlb first, or list it in the import of B.tlb using the include() option.
Only #import the parts of the interface you plan to use if you can avoid bringing in other references unnecessarily.
The easiest way it is place all *.tlb files in dir when they are used.
Depends on your project configuration. Copy all *.tlb files into: $(OutDir), $(ProjectDir), dir where is file with #import, dir when you generate *.tlb etc
Regards,
Mariusz