How to import a haskell module that uses FFI without refering to the c object? - c

I'm trying to write a haskell module that wraps a bunch of c functions.
I want to be able to import this module like any other haskell module without referring to the c object files.
I can't find any examples about how to do this.
This is what I've tried. I have a c file "dumbCfunctions.c":
double addThree(double x) {
return x+3;
}
and a haskell file with a module defined in it "Callfunctions.hs"
module Callfunctions (
addThree
) where
import Foreign.C
foreign import ccall "addThree" addThree :: Double -> Double
main = print $ addThree 4
I can make an executable doing:
ghc --make -o cf_ex Callfunctions.hs dumbCfunctions.o
Which correctly gives me 7.
I can also import it into ghic by calling ghci with
shane> ghci dumbCfunctions.o
Prelude> :l Callfunctions.hs
[1 of 1] Compiling Callfunctions ( Callfunctions.hs, interpreted )
Ok, modules loaded: Callfunctions.
*Callfunctions> addThree 3
6.0
But I want to be able to treat it like any other module with out referring to "dumbCfunctions.o":
shane> ghci
Prelude> :l Callfunctions.hs
[1 of 1] Compiling Callfunctions ( Callfunctions.hs, interpreted )
Ok, modules loaded: Callfunctions.
*Callfunctions> addThree 3
But now I get the error
ByteCodeLink: can't find label
During interactive linking, GHCi couldn't find the following symbol:
addThree
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. Restart GHCi, specifying
the missing library using the -L/path/to/object/dir and -lmissinglibname
flags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please send a bug report to:
glasgow-haskell-bugs#haskell.org
This makes sense because I haven't refereed to the object anywhere. So I must be able to do something better by first compiling the module, but I couldn't find out how to do this. I must be looking in the wrong places.

You can create a library through Cabal, and cabal install it.
This would link the C code inside your Haskell library. Later on, when you load the module, you will not need to manually load the C parts.

Related

Go compile returns duplicate symbols for architecture x86_64 error when I import 2 different packages which use C package via Cgo

Here is my code:
package main
import (
kusb "github.com/karalabe/usb"
tusb "github.com/trezor/trezord-go/usb"
)
func main() {
kusb.Enumerate(0, 0)
tusb.InitHIDAPI(nil)
}
When I compile (I'm using go mod to manage the packages), it returns this error:
duplicate symbol _libusb_dev_mem_alloc in:
/var/folders/fm/1rln65d94mn45s0h5l78tdyh0000gp/T/go-link-624554542/000002.o
/var/folders/fm/1rln65d94mn45s0h5l78tdyh0000gp/T/go-link-624554542/000020.o
ld: 136 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Why?
Some investigation i had:
The both packages use the same hidapi and libusb C packages in order to interact with usb devices.
Those C packages are identical, hence it defines the same functions so i think it is directly related to the error.
in trezord-go/usb, they include .C file, not the header file.
It is very counterintuitive to me because in the perspective of package users, I shouldn't need to worry about how a C package is used in the internal of the package, only the exposed types, functions and its behaviors.
Can anyone really explain what is going on here and how can I import both of them? They do different functions, eventhough they use the same C package.
From here: https://www.repustate.com/blog/go-duplicate-symbols-for-architecture-x86_64/
"What does this mean? Well, it means we're trying to link the same symbol name (in our case, a method) from two (or more) different source files. The fix was easy: rename one of the methods by updating the header file, the source file (.c or .cpp file) and lastly, updating your references to the symbol in your Go code, if it is directly referenced there."
Will it help ?
I was running into the same issue for hours and finally found the fix on a google groups channel
A package you import could be using cgo, you don't have to be using it directly
...
You can try CGO_ENABLED=0 go build and if it works then it is cgo related.
This was the charm that i was looking for! Hope this works for you too.

Sharing C functions between two XS Perl modues

I have a Perl module A that is a XS based module. I have an A.xs file, and an aux_A.c file, where I have some standard C functions. I use DynaLoader, and it works file.
Now, I have a new module B, that is also a XS module. I also have the B.xs file, and the aux_B.c file. Now, I want that a standard C function defined in aux_B.c file to be able to use a function defined in aux_A.c file.
One option is to make A module to create a standard C library, and link B module with it. But I was trying to get away from that option.
Is there any other way to go?
What I am currently getting is DynaLoader complaining on undefined symbol when trying to load the B.so library.
Thanks
Alberto
To make module A export its C symbols with DynaLoader, you have to add the following to A.pm:
sub dl_load_flags { 1 }
This is badly documented, unfortunately. See this thread on PerlMonks and the DynaLoadersource code for more details. The effect of the flag is to set RTLD_GLOBAL when loading A.so with dlopen which makes its symbols available to other shared objects.

cannot find symbol "Embeddedrcall_Init"

I am trying to create a dll file using swig for an embeddedR C Program in windows environment. I am using the below commands:
C:\swigwin-3.0.12\Examples\r\Z>swig -c++ -tcl embeddedRCall.i
C:\swigwin-3.0.12\Examples\r\Z>gcc -c embeddedRCall.c -I/swigwin-3.0.12/Examples/r/Z
C:\swigwin-3.0.12\Examples\r\Z>gcc -c embeddedRCall_wrap.c -I/Tcl/include/tcl8.6 -I/swigwin-3.0.12/Examples/r/Z
C:\swigwin-3.0.12\Examples\r\Z>gcc -shared embeddedRCall.o embeddedRCall_wrap.o -o embeddedRCall.dll -L/Tcl/lib -L/R/R-3.3.2/bin/i386 -lR -lRblas -lRiconv -lRlapack -ltcl86
% load embeddedRCall
cannot find symbol "Embeddedrcall_Init"
I was able to load other example.dll files with tclsh
However I was unable to figure out the reason-- I am already using tcl 32 bit
My module file name is and module name is embeddedRcall
Am I missing something???
I am relatively new to TCL can someone please help me.
You should have an exported (extern "C") function symbol in your library called something like Embeddedrcall_Init; it is the entry point that lets Tcl install the library into a specific interpreter instance. (It has to be found explicitly because it takes an argument.) By default, the name of the function is found by munging the name of the library (strip version number, case convert, append _Init) but the determination of the name can be overridden by the optional second argument to load.
To be more exact, if the entry is actually called EmbeddedRCall_Init, you would have to load it with:
load embeddedRCall EmbeddedRCall
# The _Init suffix is fixed when loading into a standard interp
Note the case difference! (Also, we recommend using fully qualified path names to loaded libraries, as it avoids some complexities in the dlopen() system.)

perl syntax check without loading c library

I would like to check syntax of my perl module (as well as for imports), but I don't want to check for dynamic loaded c libraries.
If I do:
perl -c path_to_module
I get:
Can't locate loadable object for module B::Hooks::OP::Check in #INC
because B::Hooks::OP::Check are loading some dynamic c libraries and I don't want to check that...
You can't.
Modules can affect the scripts that use them in many ways, including how they are parsed.
For example, if a module exports
sub f() { }
Then
my $f = f+4;
means
my $f = f() + 4;
But if a it were to export
sub f { }
the same code means
my $f = f(+4);
As such, modules must be loaded to parse the script that loads it. To load a module is simply to execute it, be it written in Perl or C.
That said, some folks put together PPI to address the needs of people like you. It's not perfect —it can't be perfect for the reasons previously stated— but it will give useful results nonetheless.
By the way, the proper way to syntax check a module is
perl -e'use Module;'
Using -c can give errors where non exists and vice-versa.
The syntax checker loads the included libraries because they might be applying changes to the syntax. If you're certain that this is not happening, you could prevent the inclusion by manipulating the loading path and providing a fake b::Hooks::OP::Check.

How do you export a system library using cmake?

How can I export the libraries that a cmake library depends on, such that an executable depending on that library does not have to manually depend on the dependencies of that library?
That's a bit of a mouthful, so here's an example:
dummy (application) ----> depends on liba
liba ----> depends on libpng
Compiling dummy generates errors:
-- Found LIBPNG
-- Found LIBA
-- Configuring done
-- Generating done
-- Build files have been written to: /home/doug/projects/dummy/build
Linking C executable dummy
../deps/liba/build/liba.a(a.c.o): In function `a_dummy':
/home/doug/projects/dummy/deps/liba/src/a.c:6: undefined reference to `png_sig_cmp'
collect2: ld returned 1 exit status
make[2]: *** [dummy] Error 1
make[1]: *** [CMakeFiles/dummy.dir/all] Error 2
make: *** [all] Error 2
I can fix that by adding this into CMakeLists.txt for dummy:
TARGET_LINK_LIBRARIES(dummy png)
However, dummy has no knowledge of how liba implements its api. At some point that may change to being libjpg, or something else, which will break the dummy application.
After getting some help from the cmake mailing list I've been directed to this example for exporting things:
http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
However, following that approach leaves me stuck at this line:
export(TARGETS ${LIBPNG_LIBRARY} FILE "${PROJECT_BINARY_DIR}/ALibraryDepends.cmake")
Clearly I'm missing something here; this 'export' command looks like its designed to export sub-projects to a high level; ie. nested projects inside liba.
However, that is not the problem here.
When configuring liba (or any cmake library) I will always generate a list of dependencies which are not part of that project.
How can I export those so they appear as part of LIBA_LIBRARY when I use find_package() to resolve liba?
Using static libraries is not an option (static library for something that links to opengl? no.)
Given your comment to arrowdodger's answer about the fear of
installing something would mess up your system I chose to give
a conceptional comment in form of an answer because of its
length.
Chaining cmake project works via find_package, which looks for
*Config.cmake and *-config.cmake files.
Project A's CMakeLists.txt:
#CMakeLists.txt
project(A)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/AConfig.cmake share/A/cmake
)
#AConfig.cmake
message("Yepp, you've found me.")
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install
Project B's CMakeLists.txt:
project(B)
find_package(A)
Then
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install
results in
...
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Yepp, you've found me.
B found A because it installed AConfig.cmake into a location
where cmake will find it 'share/A/cmake' AND was given the same
value for CMAKE_INSTALL_PREFIX.
Now this is that. Lets think about what you can do in
AConfig.cmake: AFAIK everything you want to. But the most common
task is to pull information about the targets of A via include(),
do some additional find_package invoctions for 3rd party
packages (HINT HINT) and create the variables
A_LIBRARIES
A_INCLUDE_DIRS
What you want to include is a file that was created by
install(EXPORT A-targets
DESTINATION share/A/cmake
)
in A's CMakeLists.txt , where A-targets refers to a global cmake
variable that accumulated all target informations when used in
install(TARGETS ...
EXPORT A-targets
...
)
statments. What is created at make install is
/tmp/test-install/share/A/cmake/A-targets.cmake
which then resides alongside AConfig.cmake in the same directory.
Please take another look at the wiki page on how to use this file
within AConfig.cmake.
Regarding the export() command: This comes handy if your
projects have gotten HUGE and it takes a considerable amount of
time to install them. To speed things up, you want to use what's
in A's build/ directory directly. It's an optimization and also
explained in the wiki. It still works via find_package(), see
http://cmake.org/cmake/help/cmake-2-8-docs.html#command:export
But I strongly suggest that you go for the usual make install
route for now.
I found my own solution to this problem using the accepted solution above, which I leave here for others:
In liba/CMakeLists.txt:
# Self
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/include")
set(A_LIBRARIES ${A_LIBRARIES} "${PROJECT_BINARY_DIR}/liba.a")
# Libpng
FIND_PACKAGE(libpng REQUIRED)
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} ${LIBPNG_INCLUDE_DIRS})
set(A_LIBRARIES ${A_LIBRARIES} ${LIBPNG_LIBRARIES})
ADD_LIBRARY(a ${SOURCES})
# Includes
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
# Allow other projects to use this
configure_file(AConfig.cmake.in "${PROJECT_BINARY_DIR}/AConfig.cmake")
In liba/AConfig.cmake:
set(A_LIBRARIES #A_LIBRARIES#)
set(A_INCLUDE_DIRS #A_INCLUDE_DIRS#)
In dummy/CMakeLists.txt:
FIND_PACKAGE(A REQUIRED)
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(dummy ${A_LIBRARIES})
This yields an AConfig.cmake that reads:
set(A_LIBRARIES /home/doug/projects/dummy/deps/liba/build/liba.a;/usr/lib/libpng.so)
set(A_INCLUDE_DIRS /home/doug/projects/dummy/deps/liba/include;/usr/include)
And a verbose compile that reads:
/usr/bin/gcc -std=c99 -g CMakeFiles/dummy.dir/src/main.c.o -o dummy -rdynamic ../deps/liba/build/liba.a -lpng
Which is exactly what I was looking for.
If liba doesn't provide any means to determine it's dependencies, you can't do anything.
If liba is library developed by you and you are using CMake to build it, then you should install libaConfig.cmake file with liba itself, which would contain necessary definitions. Then you include libaConfig in dummy's CMakeLists.txt to obtain information about how liba have been built.
You can look how it's done in LLVM project, relevant files have cmake.in extension
http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/
In the end, in dummy project you should use
target_link_libraries( ${LIBA_LIBRARIES} )
include_directories( ${LIBA_INCLUDE_DIR} )
link_directories( ${LIBA_LIBRARY_DIR} )
If that liba is used only by dummy, you can build it from single CMake project. This is more convenient, since you don't need to install liba each time you recompile it and it will be rebuilt and relinked with dummy automatically every time you run make.
If you liked this approach, the only thing you should do - define in liba' CMakeLists.txt variables you need with PARENT_SCOPE option (see set() command manual).
Finally, you can use shared libs, .so's don't have such problem.

Resources