Skip to content

nyaosorg/go-importconst

Repository files navigation

go-importconst

When you want to refer to a constant defined in a C header from Go code, you typically have to use cgo or manually copy the value. This introduces a C compiler as a build-time dependency.

With go-importconst, the C compiler is required only at go generate time, not at go build time. This enables projects to avoid requiring a C compiler for regular builds.

go-importconst is invoked by go generate to generate, compile, and execute a temporary C++ source file. This C++ program emits Go source code that defines the requested constants.

From const.go:

package dos

//go:generate go run github.com/nyaosorg/go-importconst
//	<windows.h>
//	RESOURCE_CONNECTED
//	RESOURCE_CONTEXT
//	RESOURCE_GLOBALNET
//	RESOURCE_REMEMBERED
//	RESOURCETYPE_ANY
//	RESOURCETYPE_DISK
//	RESOURCETYPE_PRINT
//	RESOURCEDISPLAYTYPE_NETWORK
//	RESOURCEDISPLAYTYPE_SERVER
//	RESOURCEUSAGE_CONNECTABLE
//	RESOURCEUSAGE_CONTAINER
//	RESOURCEUSAGE_ATTACHED
//	RESOURCEUSAGE_ALL
//	ERROR_NO_MORE_ITEMS
//	CONNECT_UPDATE_PROFILE
//	S_OK

Running go generate produces a Go source file (zconst.go) like the one below:

C:> cd example

C:> go generate -v -x
const.go
go run github.com/nyaosorg/go-importconst
C:\Users\hymkor\scoop\apps\tdm-gcc\current\bin\gcc.exe zconst.cpp
.\a.exe zconst.go
rm .\a.exe
C:\Users\hymkor\scoop\apps\go\current\bin\go.exe fmt zconst.go
rm zconst.cpp
zconst.go

C:>
package dos

// Code generated by go-importconst DO NOT EDIT.
const RESOURCE_CONNECTED = 1
const RESOURCE_CONTEXT = 5
const RESOURCE_GLOBALNET = 2
const RESOURCE_REMEMBERED = 3
const RESOURCETYPE_ANY = 0
const RESOURCETYPE_DISK = 1
const RESOURCETYPE_PRINT = 2
const RESOURCEDISPLAYTYPE_NETWORK = 6
const RESOURCEDISPLAYTYPE_SERVER = 2
const RESOURCEUSAGE_CONNECTABLE = 1
const RESOURCEUSAGE_CONTAINER = 2
const RESOURCEUSAGE_ATTACHED = 16
const RESOURCEUSAGE_ALL = 19
const ERROR_NO_MORE_ITEMS = 259
const CONNECT_UPDATE_PROFILE = 1
const S_OK = 0

Mechanism

  1. A temporary C++ source file is generated.
  2. It is compiled using a C compiler such as gcc.
  3. The resulting executable is run to write the Go source (zconst.go) to standard output.
#include <cstdio>
#include <windows.h>

void p(FILE *w,const char *name,const char *s){
	fprintf(w,"const %s = \"%s\"\n",name,s);
}
void p(FILE *w,const char *name,int n){
	fprintf(w,"const %s = %d\n",name,n);
}
void p(FILE *w,const char *name,long n){
	fprintf(w,"const %s = %ld\n",name,n);
}
void p(FILE *w,const char *name,unsigned long n){
	fprintf(w,"const %s = %lu\n",name,n);
}
void p(FILE *w,const char *name,double n){
	fprintf(w,"const %s = %lf\n",name,n);
}

int main(int argc,char **argv)
{
    if ( argc < 2 ){ return 1; }
    FILE *w=fopen(argv[1],"wb");
    if ( w == NULL ){ return 2; }
    fprintf(w,"package dos\n\n");
    fprintf(w,"// Code generated by go-importconst DO NOT EDIT.\n");
    p(w,"RESOURCE_CONNECTED",RESOURCE_CONNECTED);
    p(w,"RESOURCE_CONTEXT",RESOURCE_CONTEXT);
    p(w,"RESOURCE_GLOBALNET",RESOURCE_GLOBALNET);
    p(w,"RESOURCE_REMEMBERED",RESOURCE_REMEMBERED);
    p(w,"RESOURCETYPE_ANY",RESOURCETYPE_ANY);
    p(w,"RESOURCETYPE_DISK",RESOURCETYPE_DISK);
    p(w,"RESOURCETYPE_PRINT",RESOURCETYPE_PRINT);
    p(w,"RESOURCEDISPLAYTYPE_NETWORK",RESOURCEDISPLAYTYPE_NETWORK);
    p(w,"RESOURCEDISPLAYTYPE_SERVER",RESOURCEDISPLAYTYPE_SERVER);
    p(w,"RESOURCEUSAGE_CONNECTABLE",RESOURCEUSAGE_CONNECTABLE);
    p(w,"RESOURCEUSAGE_CONTAINER",RESOURCEUSAGE_CONTAINER);
    p(w,"RESOURCEUSAGE_ATTACHED",RESOURCEUSAGE_ATTACHED);
    p(w,"RESOURCEUSAGE_ALL",RESOURCEUSAGE_ALL);
    p(w,"ERROR_NO_MORE_ITEMS",ERROR_NO_MORE_ITEMS);
    p(w,"CONNECT_UPDATE_PROFILE",CONNECT_UPDATE_PROFILE);
    p(w,"S_OK",S_OK);
    fclose(w);
    return 0;
}

Install

If you want to use:

//go:generate go-importconst ...

instead of:

//go:generate go run github.com/nyaosorg/go-importconst ...

you can install the binary from the releases page.

Download the binary from Releases and place it in your PATH.

For scoop users:

scoop install https://raw.githubusercontent.com/nyaosorg/go-importconst/master/go-importconst.json

or:

scoop bucket add nyaosorg https://github.com/nyaosorg/scoop-bucket
scoop install go-importconst

Options

  • -c Clean output (removes temporary files)

  • -cc string C compiler command (default "gcc")

  • -csrc string Temporary C source filename (default "zconst.cpp")

  • -d Enable debug output

  • -lowercamel Convert AAA_BBB_CCC to aaaBbbCcc

  • -nofmt Do not run go fmt (for debugging)

  • -o string Output filename for generated Go source (default "zconst.go")

  • -prefix string Add this string as a prefix to constant names

  • -uppercamel Convert AAA_BBB_CCC to AaaBbbCcc

Author

hymkor (HAYAMA Kaoru)

License

You may use, copy, and modify this software under the terms of the MIT License.

About

Convert C/C++ constants to Go without cgo

Topics

Resources

License

Stars

Watchers

Forks