Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go type not supported in export #65842

Closed
raphael10-collab opened this issue Feb 21, 2024 · 3 comments
Closed

Go type not supported in export #65842

raphael10-collab opened this issue Feb 21, 2024 · 3 comments

Comments

@raphael10-collab
Copy link

Go version

go version go1.21.5 linux/amd64

Output of go env in your module/workspace:

raphy@raohy:~$ go env
GO111MODULE='on'
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/raphy/.cache/go-build'
GOENV='/home/raphy/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/raphy/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/raphy/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.5'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build222890560=/tmp/go-build -gno-record-gcc-switches'

What did you do?

I would like to call functions available in this golang library: https://github.com/pemistahl/lingua-go in a Cpp piece of code

I tried to generate h and `so' files for this very simple code:

basic.go :

package main

import "C"

import (
        "github.com/pemistahl/lingua-go"
)

var lan lingua.Language

//export Langdetectfunct
func Langdetectfunct(text string) lingua.Language {

    detector := lingua.NewLanguageDetectorBuilder().
        FromAllLanguages().
        Build()

    if language, exists := detector.DetectLanguageOf(text); exists {
        lan = language
    }
    lan = lingua.English

    return lan

}

//export Add
func Add(a, b int) int {
        return a + b
}

func main() {}

What did you see happen?

But building with c-shared buildmode gives this error:

raphy@raohy:~/go-lang-detect$ go build -o basic.so -buildmode=c-shared basic.go
# command-line-arguments
./basic.go:14:35: Go type not supported in export: lingua.Language

I searched for info about this kind of errors and found this:
#18412

What can I do to be able to export, and use, this lingua.Language structure?

What did you expect to see?

I would like to be able to to export and then use this lingua.Language structure

@gophun
Copy link

gophun commented Feb 21, 2024

What can I do to be able to export, and use, this lingua.Language structure?

Since the Language type is based on int and not a struct type, you can convert it to int and change the function's return type to int, because ints can be exported to C.

@raphael10-collab
Copy link
Author

Hi @gophun

returning the int(lan) solves the issue :

basic.go :

package main

import "C"

import (
        "github.com/pemistahl/lingua-go"
)

var lan lingua.Language

//var lan int

//export Langdetectfunct
func Langdetectfunct(text string) int {

    detector := lingua.NewLanguageDetectorBuilder().
        FromAllLanguages().
        Build()

    if language, exists := detector.DetectLanguageOf(text); exists {
        lan = language
    }
    lan = lingua.English

    return int(lan)

}

func main() {}

Building:

raphy@raohy:~/go-lang-detect$ go build -o basic.so -buildmode=c-shared basic.go

basic.h :

/* Code generated by cmd/cgo; DO NOT EDIT. */

/* package command-line-arguments */


#line 1 "cgo-builtin-export-prolog"

#include <stddef.h>

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif

#endif

/* Start of preamble from import "C" comments.  */




/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef size_t GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
#ifdef _MSC_VER
#include <complex.h>
typedef _Fcomplex GoComplex64;
typedef _Dcomplex GoComplex128;
#else
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
#endif

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif

extern GoInt Langdetectfunct(GoString text);

#ifdef __cplusplus
}
#endif

basic.so :

raphy@raohy:~/go-lang-detect$ file basic.so
basic.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=2368dc7620b47d7b9b8ba019796d66f76fe061b8, with debug_info, not stripped

raphy@raohy:~/go-lang-detect$ nm basic.so | grep -e "T Langdetectfunct"
0000000000241350 T Langdetectfunct

Last question:

Since type Language is actually an int :

image

why do I have to "convert" it into an int with int(lan) ?

@gophun
Copy link

gophun commented Feb 21, 2024

Since type Language is actually an int
why do I have to "convert" it into an int with int(lan) ?

It's not an int, it's a new type based on int. That makes a difference. Go is a strongly typed language, it doesn't implicitly convert from one type to another, see https://go.dev/doc/faq#conversions

For further questions please refer to https://github.com/golang/go/wiki/Questions

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants