How to use this portaudio Go binding? - go

I'm trying to dynamically play audio in a Go application. Basically the only way I found was to use a Go binding to call a C library, more specifically portaudio.
I found this binding but I don't know how to use it. I downloaded these pre-compiled DLLs and replaced the lines
/*
#cgo pkg-config: portaudio-2.0
#include <portaudio.h>
extern PaStreamCallback* paStreamCallback;
*/
with
/*
#cgo LDFLAGS: -LC:\portaudio-binaries -lportaudio
#include "portaudio.h"
extern PaStreamCallback* paStreamCallback;
*/
but when I try to compile the Go project I still get
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
I also got this error when trying to import versions of portaudio I compiled using mingw. Its output had the format of a .la file alongside a .libs folder, which contained a .dll file plus others. But I'm not sure how I'm supposed to import this format of libraries.

Related

Cgo "undefined reference" (gstreamer)

I am writing something using cgo to interact with the gstreamer-1.0 library. I have everything almost working perfectly, but for some reason an entire header file's objects are not getting imported correctly.
go version go1.15.2 linux/amd64 for whatever that is worth
package main
// #cgo pkg-config: gstreamer-1.0
// #cgo CFLAGS: -Wno-deprecated-declarations
// #include <gst/gst.h> // using this file extensively with no issues
// #include <gst/app/gstappsink.h> // objects in this file are not getting read, but the compiler is having no issue reading it
import "C"
func init () { C.gst_init(nil, nil) }
func main () {
// ...
C.gst_app_sink_pull_sample() // a non-variadic function that does take args
// but cgo doesn't even think it exists.
// ...
}
The error back from the compiler: /tmp/go-build/cgo-gcc-prolog:64: undefined reference to 'gst_app_sink_pull_sample'
I've looked at the header file and gst_app_sink_pull_sample is indeed there. I can reproduce this both trying to build locally and in the golang docker container.
If I remove the include entirely the error is different: could not determine kind of name for C.gst_app_sink_pull_sample.
So am I the problem or is gstreamer the problem?
The appsrc and appsink symbols are not part of the base gstreamer library. Instead they are found in the extra library gstreamer-app-1.0. Add this library to your cgo pkgconfig line and it should find the missing symbols.
"undefined reference to xxx" means the C compiler of cgo recognize the definitions but it can't find the implementations (covered by corresponding C libraries)
This indicates that you have your C header files imported correctly. To solve the undefined reference problem, you just have to add some thing as below if your dynamic library is called libgstreamer.so.1.0.0
# cgo LDFLAGS: -lgstreamer

Include libsodium using cgo in go project fails

I am trying to include the libsodium into my Go project. For that, I've copied the repo inside my project
// #cgo CFLAGS: -I/mypath/libsodium/src/libsodium/include/sodium
// #include <stdlib.h>
// #include "crypto_sign_ed25519.h"
import "C"
When trying to build the project I get the following error:
/tmp/go-build/cgo-gcc-prolog:53: undefined reference to `crypto_sign_ed25519_pk_to_curve25519'
collect2: error: ld returned 1 exit status
The file can be found but the error is there.
I've also tried to reference the '.c' file as well as to copy the crypto_sign_ed25519.h into the src folder but it does not work.
My question is do I have to add LDFLAGS and therefore generate a .so file from the library or that is not needed and there is another possible way of doing it?
UPDATE: I've achieved to make it running by installing the library on my local ubuntu:
$ ./configure
$ make && make check
$ sudo make install
and adding
// #cgo LDFLAGS: -L/usr/local/lib -lsodium
But how can I do it without adding the local path?
You indeed need to link the library, the headers themselves are only the interface to the library and don't link the actual libsodium code to your binary.
Assuming libsodium ships a pkg-config file (it seems to be the case), you can use something like
// #cgo pkg-config: libsodium
// #include "crypto_sign_ed25519.h"
See https://golang.org/cmd/cgo/ for more information about pkg-config support.
To see what cflags/libs you'd be getting (so what cgo will use), run:
pkg-config --cflags --libs libsodium
After manually installing a library on Linux, you have to type ldconfig so that the linker becomes aware of it.
Also, in order to get libsodium prototypes, you should simply include <sodium.h> not <sodium/crypto_sign_ed25519.h> (not meant to be included directly), and call sodium_init() before any other function so that internal data structures are properly initialized.
See how this is done in existing bindings for Go: https://github.com/jamesruan/sodium/blob/master/core.go
You may want to use these bindings instead of reinventing your own. If they are missing some of the functions you need, their maintainers will probably be happy to accept your pull requests.
The two main Go bindings for libsodium that I am aware of are sodium and libsodium-go.

Golang cgo error while loading shared library (libcrypto) on other computers

I wrote a go package that is just a wrapper for a C program, which requires openssl to work.
My CGO setup is as follow:
// #cgo CFLAGS: -Imy/library/include -Imy/library/src -I/usr/local/opt/openssl/include
// #cgo LDFLAGS: -L/usr/include/openssl -Lmy/library/src -lcrypto
// #include <my_library.c>
// #include <stdlib.h>
import "C"
I can compile and run it both in my Mac and on a Docker container I created, but when I try to run (it is already compiled) on a different machine I get the error:
error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory
How can I make it work also on PCs without libssl-dev installed?

xcode can't load GLFW which compile by CMake

I follows the CMake org and this one attempt to load the library but failed.
I have use make install put GLFW to /usr/local/include/GLFW/, and then, I add the directory to Link Binary With Libraries in XCode project.
But #include <GLFW/glfw3.h> said the file not found.
How to load the library? thanks
It's my first time use cmake, I mess all things. To import the library should add /usr/local/include/ to Header Search Paths and add /usr/local/lib/ to Library Search Paths, besides, Link Binary With Libraries should add libglfw3.a in /usr/local/lib/.
import with #include <GLFW/glfw3.h>

go build doesn't find my C standard library when compiling cgo package

I'm trying to compile a go project in a raspberry pi.
The project has 5 files, two small .c files and its counterparts .h (one of these files is my code -- it calls the other, which is a base64 library) and a .go files which calls my .c code using cgo.
When I compile my C code only (with its calls and everything) with gcc alone at the raspberry pi it does well without any configuration.
When I compile the entire go project on my x86 Linux Ubuntu machine with go build, it also does pretty well.
But when I try to compile the go project with go build in the raspberry pi it doesn't get my C libraries:
fiatjaf#raspberrypi ~/g/s/b/f/project> go build -x
WORK=/tmp/go-build702187084
mkdir -p $WORK/bitbucket.org/fiatjaf/project/_obj/
cd /home/fiatjaf/go/src/bitbucket.org/fiatjaf/project
/usr/lib/go/pkg/tool/linux_arm/5c -FVw -I $WORK/bitbucket.org/fiatjaf/project/_obj/ -I /usr/lib/go/pkg/linux_arm -o $WORK/bitbucket.org/fiatjaf/project/_obj/base64.5 -DGOOS_linux -DGOARCH_arm ./base64.c
# bitbucket.org/fiatjaf/project
./base64.c:2 5c: No such file or directory: math.h
(If I put the <stdlib.h> before the <math.h> the problem occurs for it too, so the problem is not the absence of math.h, I think)
I tried to:
add // #cgo CFLAGS: -I/usr/include to the .go file
add // #cgo LDFLAGS: -I/usr/include (I can't discover what is the proper usage of these flags)
use go build -ldflags '-I/usr/include'
I don't understand why go is trying to compile base64.c with -I /usr/lib/go/pkg/linux_arm. Really don't. Someone help.
EDIT: Clarifying note about the structure of the project:
It has 5 files, 2 C (and its counterparts H):
base64.c
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
... // definitions of functions used at project.c
project.c
#include <stdlib.h>
#include <string.h>
#include "base64.h"
... // functions used at project.go
and 1 Go:
...
// #include <stdlib.h>
// #include <string.h>
// #include "project.h"
// #cgo CFLAGS: -I/usr/include
// #cgo LDFLAGS: -lm
import "C"
...
Where, what and how should I change in this declarations for this thing to work? And why did it worked on my x86 linux?
cgo inline syntax
The correct syntax for cgo parameters in the go file is this:
// #cgo CFLAGS: -I/usr/include
without the whitespace between # and cgo. See cmd/cgo for details on the syntax.
-ldflags parameter
The go -ldflags parameter passes parameters to the go linkers (5l, 6l, 8l, ...).
Even if the parameter would be passed to the C linker, this wouldn't do you any good
as the linker does not handle includes, the compiler does.
I'm afraid that this parameter won't help you here. All relevant parameters should
be configured in the go source file using the #cgo tags.
misc. notes
If you're using math.h you most likely need to link libmath. You can do this
by writing this to your go source file:
// #cgo LDFLAGS: -lm
It seems my problem was something related to not having set the CGO_ENABLED flag.
I don't know for sure, but it seems, because I uninstalled my Go from the Raspbian repositories (which seems to come with CGO disabled by default) and installed Go from source (just like I had made in my x86 Linux) then it started to work.

Resources