Kotlin/Native Windows cinterop using built library dll - c

I am using Windows to follow the Kotlin-Native libcurl example here https://kotlinlang.org/docs/tutorials/native/curl.html
Unfortunately, this has been a bigger challenge then I could have imagined. I have been learning how to compile C binaries on windows from source using tools such as CMake and have followed this tutorial to build libcurl on Windows: https://jonnyzzz.com/blog/2018/10/29/kn-libcurl-windows/
After quite a few days of trial and error with the .def file for cinterop on Windows, and using compilerOpts to point to my header file for curl in my built library, I have hit a brick wall.
I can't seem to get Gradle to recognize the dll file. Task ':linkDebugExecutableMingw' keeps failing. I have no idea where I am supposed to put the dll file. I have tried putting it in to the build output folder next to the exe, but it still fails to compile, with this error:
C:\Users\yous\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1\bin\ld: C:\Users\yous\AppData\Local\Temp\konan_temp6326583690522756621\result.o:out:(.rdata$.refptr.knifunptr_sample35_curl_easy_strerror[.refptr.knifunptr_sample35_curl_easy_strerror]+0x0): undefined reference to `knifunptr_sample35_curl_easy_strerror'
And a similar list of header file errors, then the final message is:
e: C:\Users\yabde\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1/bin/clang++ invocation reported errors
This is after I succesfully located the header files. I believe this is an issue with the dll file not being included.
Here is my relevant Gradle build script:
mingwX64("mingw") {
compilations.main {
cinterops {
libcurl {
// Def-file describing the native API.
// The default path is src/nativeInterop/cinterop/<interop-name>.def
defFile project.file("src/nativeInterop/cinterop/libcurl.def")
// Package to place the Kotlin API generated.
packageName 'libcurl'
// Options to be passed to compiler by cinterop tool.
compilerOpts '-Isrc\\nativeInterop\\cinterop\\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\\include -o libcurl'
//linkerOpts '-Isrc\\nativeInterop\\cinterop\\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\\bin'
// Directories for header search (an analogue of the -I<path> compiler option).
//includeDirs.allHeaders("path1", "path2")
// Additional directories to search headers listed in the 'headerFilter' def-file option.
// -headerFilterAdditionalSearchPrefix command line option analogue.
includeDirs.headerFilterOnly("src/nativeInterop/cinterop/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/include")
// A shortcut for includeDirs.allHeaders.
//includeDirs("include/directory", "another/directory")
}
}
}
binaries {
executable {
// Change to specify fully qualified name of your application's entry point:
entryPoint = 'sample.main'
// Specify command-line arguments, if necessary:
//runTask?.args('-Lsrc/nativeInterop/cinterop/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/bin')
runTask?.args('')
}
}
}
I believe this issue may be with linker options to locate the dll, but uncommenting the linkerOpts line does not help.
I think I have given up on Kotlin/Native and will be sticking to C for data-oriented native programming...
EDIT:
Also, note that any text commented out is things that I have attempted
Ok so, this is my def file:
headers = curl/curl.h
headerFilter = curl/*
compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu
linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl
linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl
linkerOpts.mingw = -Llibcurl-vc-x86-release-dll-ipv6-sspi-winssl/lib
Ok so, this is my project structure:

I followed the same steps (jonyzzz blog). I created a Libcurl static example for Kotlin-Native. Support for gzip and SSL. Compile to standalone exe, no need for dll
https://github.com/carlosrafp/Libcurl-Kotlin-Native-standalone
I built the static libraries supplied on the repository with mingw64 (gzip and libcurl) and msys2/mingw (openssl)

I went through this question several times when looking for a solution for statically linking libcurl with my binary.
In the end, I ended up using WinInet for the HTTP communication on Windows. Linux and macOS binary still rely on ktor clients with libcurl.
See my example of how to use WinInet API with Kotlin MPP: https://github.com/localazy/kotlin-mpp-wininet
For a simple HTTP communication, WinInet API is good enough and the resulting binary is much smaller and in my case, it has no additional dependencies.

Related

How do you build the Pion mediadevices webrtc example?

I was checking out Pion Mediadevices and trying to cross-compile the webrtc example for a rasperry pi zero from my windows computer. When I try to build the example though, I get these errors from Windows command prompt:
# github.com/pion/mediadevices/pkg/codec/mmal
..\..\pkg\codec\mmal\params.go:30:9: undefined: newEncoder
# github.com/pion/mediadevices/pkg/driver/microphone
..\..\pkg\driver\microphone\microphone.go:27:10: undefined: malgo.AllocatedContext
..\..\pkg\driver\microphone\microphone.go:34:2: undefined: malgo.DeviceInfo
..\..\pkg\driver\microphone\microphone.go:40:13: undefined: malgo.InitContext
..\..\pkg\driver\microphone\microphone.go:40:36: undefined: malgo.ContextConfig
..\..\pkg\driver\microphone\microphone.go:78:25: undefined: malgo.DeviceInfo
Also because the program is for the pi zero I edited the import section to have "github.com/pion/mediadevices/pkg/codec/mmal" and commented out the x264 import.
What is the correct way to build this example?
Edit: Upon further investigation, I found that the error message above:
..\..\pkg\codec\mmal\params.go:30:9: undefined: newEncoder
correlates to a call to the function newEncoder which is declared in a seperate go file, mmal.go, in the same folder as params.go. Both of these files have package mmal at the top before their imports and the folder they're contained in is also called mmal. Is there any problems there causing the function to not be viewable to params.go?
mediadevices currently uses cgo to give us access to camera/microphone and codecs. Cross-compiling in cgo is possible but you would very likely need to cross-compile mmal codec as a static library yourself, but this requires access to the source code.
Unfortunately, mmal is not an open-source library. Therefore, the only option left is to compile the library on the raspberry pi since mmal should be installed on your system already.
Note: I'm the mediadevices author šŸ˜ƒ.

How do I link a compiled ".so" library with Scons?

I have an existing .so library (libgit2), and I would like to use this within a C program (the build system is Scons). I read through the entirety of the Scons documentation for "Chapter 4. Building and Linking with Libraries", but there is no mention of how to use an existing .so library. The only mention of .so in the entirety of chapter 4 is on the first page, and it is only about Scons using a .so file for output. How do I use an existing compiled .so library in Scons?
If you are using an sconscript then you should add a LIBS= arguments and a LIBS_PATH=.
if you want to directly add it to the build line, use -L for lib path and -l to link a lib.
You can find further information here: https://scons.org/doc/0.97/HTML/scons-user/x628.html
With help from the SCons Discord server and other places, I've gotten farther than when I first posted this question. I haven't solved my specific problem of using .so libraries with GDNative, but I think I've figured out the SCons side.
As of me posting this question, the SConstruct file was able to compile working code if I didn't use libgit2 and instead just printed out the text. With only the header included, my test call to git_libgit2_version compiled but didn't run, as Godot said undefined symbol: git_libgit2_version.
First of all, you need to add the named parameter for LIBS to your env.SharedLibrary or env.Program line. The lib prefix and .so suffix seem to be added automatically, I still haven't figured out how to make it point to libgit2.so.1.0.1 (so for now I have the library copied and named as libgit2.so, but I would like to have it point to libgit2.so.1.0.1 eventually instead). Also, the SCons team suggested adding LIBPATH, but this doesn't seem to actually do anything.
library = env.SharedLibrary(target=env["target_path"] + env["target_name"] , source=sources, LIBS=['git2'])
Then, the SConstruct file needs to have this magic line:
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
With the above code, ldd will report not found, and Godot will say Error: libgit2.so.1.0: cannot open shared object file: No such file or directory (I have no idea why it's asking for .so.1.0 instead of the .so or .so.1.0.1 file, and yes I tried copying and naming as libgit2.so.1.0 and that doesn't change anything either).
I also added this, which was suggested by another GDNative user.
env.Append(LINKFLAGS=[
'-Wl,-rpath,addons/git_for_godot/gdnative/linuxbsd'
])
With all of the above code, this seems to allow ldd and Godot to find the library just fine with a relative path (when running ldd you have to be cd'd into the project folder). I can run the project fine without any errors, but the project crashes immediately after opening, with no error messages printed. If I comment out the call to git_libgit2_version but keep the header included, the file does compile and run. Any time I try to call anything from libgit2 it causes Godot to crash without printing any errors. At this point I'm stuck and I don't know what I'm doing wrong.
I did try adding libgit2 to the Dependencies section of the .gdnlib file, but this doesn't seem to affect anything. Another thing I tried which didn't work is this line (+ variants on the extension) which append to the sources list passed as the named source parameter. I'll post it here for completeness, but for the moment I have this line commented out because it doesn't work:
sources.append(File("project/addons/git_for_godot/gdnative/linuxbsd/libgit2.so"))

Biometric matching with futronic sdk using nodejs server

I have successfully taken bio-metric prints and posted to the node server using the futronic sdk. I want to be able to use this library likewise for matching in the server because that's where the bio-metric prints for all users are stored. I stubbled upon the node-ffi library that helps define equivalent C functions that I have exported and compiled it down to a .dll file.
Now the challenge here is that I have tried to port the ftrAnsiSDK functions but the ftrScanAPI.dll and the ftrAnsiSDK.dll file could not be compiled together. It gives this error:
...collect2.exe [Error] ld returned 5 exit status
When I compile and export the functions that are not dependent on these two libraries, my code works fine and the functions are easily exported and used in the node server. Please can any one give me a hint?
Here is the link to the repo. It consists of the lib and .dll library that is been used.
For the server code here is a snippet of what I am trying to achieve:
var libm = ffi.Library('lib/visystem', {
'HelloWorld': [ 'void', [] ],
'PrintErrorMessage': [ 'void', ['int'] ],
'CaprureImage': [ 'int', ['int','int','int'] ]});
The HelloWord and PrintErrorMessages are methods that I used as a test case to ensure the functions are being exported before I proceeded to the main functions (you can see the function definition in from the code in the repo.. ) that depends on the futronic lin and sdk.
I am currently using a 64-bit operation system and I installed the same program on a 32-bit machine to be sure, but it still did not compile and export the function. The code editor I am using is Dev++C.
Can anyone help or even give me hint on how to achieve this goal?
As a disclaimer, I'm not familiar with the Dev-C++ IDE or MinGW development.
However, after a cursory look at your github repo, according to your libvisystem.def file, it appears that the only functions that are exported by your DLL are:
HelloWorld
PrintErrorMessage
ReadTemplateFile
SaveBmpFile
SaveTemplateFile
This is also confirmed when looking at the libvisystem.a library header:
So you should probably start by manually add the rest of the exported functions in your dll.h to the def file, in a similar manner to the ones that are already there, and see if that changes anything.
NOTE:
I'm not sure whether the __declspec(dllexport) directive is ignored by the Dev-C++ compiler/linker and it uses the def file instead. Perhaps others on SO have an idea.

How to add a gsl library in window using the compiler tcc?

At the moment I am able to compile and run a basic "Hello World" programme by using the windows command prompt via the command:
tcc.test.c
followed by
test.exe.
where test is the name of the file contaaing the code for the "Hello World" programme.
I installed the tcc folder ontop of my c:\ drive. I have another programme that requires the gsl library to run but I don't know from where and how to correctly install the library and how to call it when the programme compiles and runs.
you might want to read the documentation at: ;.
which, amongst other things says:
-Bdir Set the path where the tcc internal libraries can be found (default is PREFIX/lib/tcc'). "
Also of interest is:
-Idir' Specify an additional include path. Include paths are searched in the order they are specified. System include paths are always searched after. The default system include paths are: /usr/local/include', /usr/include' and PREFIX/lib/tcc/include'. (PREFIX' is usually /usr' or/usr/local'). "
and finally:
-Ldir' Specify an additional static library path for the-l' option. The default library paths are /usr/local/lib',/usr/lib' and `/lib'.
-lxxx' Link your program with dynamic library libxxx.so or static library libxxx.a. The library is searched in the paths specified by the-L' option.

Installing a new library in Linux, and accessing it from my C code

I am working on a project which requires me to download and use this. Inside the downloaded folder, when extracted I am presented with three things:
A folder called "include"
A folder called "src"
A file called "Makefile"
After some research, I found out that I have to navigate to the directory which contains these files, and just type in the command make.
It seemed to install the library in my system. So I tried a sample bit of code which should use the library:
csp_conn_t * conn;
csp_packet_t * packet;
csp_socket_t * socket = csp_socket(0);
csp_bind(socket, PORT_4);
csp_listen(socket, MAX_CONNS_IN_Q);
while(1) {
conn = csp_accept(socket, TIMEOUT_MAX);
packet = csp_read(conn, TIMEOUT_NONE);
printf(ā€œ%S\r\nā€, packet->data);
csp_buffer_free(packet);
csp_close(conn);
}
That's all that was given for the sample server end of the code. So I decided to add these to the top:
#include <csp.h>
#include <csp_buffer.h>
#include <csp_config.h>
#include <csp_endian.h>
#include <csp_interface.h>
#include <csp_platorm.h>
Thinking I was on the right track, I tried to compile the code with gcc, but I was given this error:
csptest_server.c:1: fatal error: csp.h: No such file or directory
compilation terminated.
I thought I may not have installed the library correctly after all, but to make sure, I found out I could check by running this command, and getting this result:
find /usr -iname csp.h
/usr/src/linux-headers-2.6.35-28-generic/include/config/snd/sb16/csp.h
/usr/src/linux-headers-2.6.35-22-generic/include/config/snd/sb16/csp.h
So it seems like the csp.h is installed, maybe I am referencing it incorrectly in the header include line? Any insight? Thanks a lot.
The make command is probably only building the library, but not installing it. You could try sudo make install. This is the "common" method, but I recommend you to check the library's documentation, if any.
The sudo command is only necessary if you have no permissions to write the system's include and library directories, which may be your case.
Another possibility (instead of installing the library) is telling GCC the location of the library's source code and generated binaries (by means of the -I and -L options of the gcc command.
That Makefile will not install anything, just translate the source into a binary format.
The csp.h in the Linux kernel has nothing to do with your project, it's just a naming collision, likely to happen with three letter names.
In your case, I would presume you need to add the include directory to the compilation flags for your server, like gcc -I/path/to/csp/include/csp csptest_server.c.
(Next, you'll run into linker errors because you'll also want to specify -L/path/to/csp -lcsp so that the linker can find the binary code to link to.)

Resources