Git Product home page Git Product logo

cxgo's Introduction

C to Go translator

GitHub license Gitter GoDoc

CxGo is a tool for translating C source code to Go (aka transpiler, source-to-source compiler).

It uses cc for preprocessing and parsing C (no clang/gcc dependencies!) and a custom type-checker and AST translation layer to make the best output possible.

The only requirement is: C code must compile with cxgo, including headers.

Having said that, cxgo uses a few tricks to make this process easier.

TL;DR for the project goals:

  1. Implement a practical C to Go translator (no C++ for now).
  2. Keep the output program code correct.
  3. Make the generated code human-readable and as idiomatic as possible.
  4. Make it easy to use and customize.

Check the FAQ for more common question about the project.

Status

The project is experimental! Do not rely on it in production and other sensitive environments!

Although it was successfully tested on multiple projects, it might change the behavior of the code due to yet unknown bugs.

Compiler test results:

  • TCC: 62/89 (70%)
  • GCC: 783/1236 (63%)

Transpiled projects:

Installation

go install github.com/gotranspile/cxgo/cmd/cxgo@latest

or download the latest release from Github.

How to use

The fastest way to try it is:

cxgo file main.c

For more details, check our examples section.

It will guide you through basic usage patterns as well as a more advanced ones (on real-world projects).

You may also check FAQ if you have any issues.

Caveats

The following C features are currently accepted by cxgo, but may be implemented partially or not implemented at all:

  • preserving comments from C code (#2)
  • static (#4)
  • auto (#5)
  • bitfields (#6)
  • union with C-identical data layout (#7)
  • packed structs (#8)
  • asm
  • case in weird places (#9)
  • goto forbidden by Go (there is a workaround, though, see #10)
  • label variables (#11)
  • thread local storage (#12)
  • setjmp (will compile, but panics at runtime)
  • some stdlib functions and types are missing (good first issue!)
  • deep type inference (when converting to Go string/slices)
  • considering multiple #ifdef paths for different OS/envs

Community

Join our community! We'd like to hear back from you!

Contributing

See CONTRIBUTING.

License

MIT

cxgo's People

Contributors

chenrui333 avatar dennwc avatar g41797 avatar koteyur avatar nemith avatar redbow-kimee avatar totallygamerjet avatar yeaseen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cxgo's Issues

Case in weird places

C supports case in weird places. They are basically goto labels, so they may be inside an if statement.

We need to collect some real-world example for this. If it's common enough, we can solve it by some heavy AST rewrites of those switch statements.

negative pointer addition overflows uintptr

Given this C code:

int main() {
  int *ptr = 0;
  ptr -= 3;
  return 0;
}

Results in this Go Code:

package main

import (
	"os"
	"unsafe"
)

func main() {
	var ptr *int = nil
	ptr = (*int)(unsafe.Add(unsafe.Pointer(ptr), -(unsafe.Sizeof(int(0)) * 3)))
	os.Exit(0)
}

The negative number overflows uintptr from unsafe.Sizeof. Just casting it to any signed number fixes the error. Should it be a cast to int because that is usually the same size as the register like uintptr?

panic for typedef of void

From struct_FILE.h:

#ifndef _IO_lock_t_defined
typedef void _IO_lock_t;
#endif

Result:
2023/04/08 07:47:14 ipptool.c
panic: TODO: typedef of void? /usr/include/bits/types/struct_FILE.h:43:14

I cannot define _IO_lock_t_defined via yml, because
"...# error "_IO_lock_t_defined should only be defined when building libc itself"

convert.go:

					if vt == nil {
						panic("TODO: typedef of void? " + id.Position().String())
					}

Is there workaround for this case?

block statement inside if gets removed

Using a define that contains a block scope inside of an if statement removes the brackets. Given:

#define send_bits(s) \
{ int t = s;\
}

void main() {
  int s;
  if (0) {
    send_bits(s)
    send_bits(s)
    send_bits(s)
  }
}

The generated code:

package main

func main() {
	var s int
	if false {
		var t int = s
		_ = t
		var t int = s
		_ = t
		var t int = s
		_ = t
	}
}

I would expect there to be an inner bracket for each time the define is used. This might be an issue with the preprocessor but I didn't know if CXGO does some "optimization" that would remove these brackets unintentionally. If there isn't an if statement the brackets are generated.

Preserve comments

Currently cxgo cannot translate any comments. To make it work, we need some support from cc side.

calling a function from an array access panics

This C code panics:

void foo(void) {}

static void (*functions[1])(void) = {
    foo,
};

void main() {
    functions[0]();
}

with error:

panic: expected type must be set

goroutine 1 [running]:
github.com/gotranspile/cxgo.(*translator).ToFunc(0x1400040ca00, {0x105199000, 0x14000532e10}, 0x0)
        /Users/jarrettkuklis/GolandProjects/cxgo/funcs.go:462 +0x400
github.com/gotranspile/cxgo.(*translator).convertPostfixExpr(0x1400040ca00, 0x1400046edc0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:1013 +0x9a8
github.com/gotranspile/cxgo.(*translator).convertUnaryExpr(0x1400040ca00, 0x14000474540)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:1070 +0x1d4
github.com/gotranspile/cxgo.(*translator).convertCastExpr(0x1400040ca00, 0x14000470bd0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:1052 +0x16c
github.com/gotranspile/cxgo.(*translator).convertMulExpr(0x1400040ca00, 0x14000473880)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:661 +0x18c
github.com/gotranspile/cxgo.(*translator).convertAddExpr(0x1400040ca00, 0x140004738f0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:685 +0x178
github.com/gotranspile/cxgo.(*translator).convertShiftExpr(0x1400040ca00, 0x14000473960)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:707 +0x178
github.com/gotranspile/cxgo.(*translator).convertRelExpr(0x1400040ca00, 0x140004739d0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:729 +0x154
github.com/gotranspile/cxgo.(*translator).convertEqExpr(0x1400040ca00, 0x14000473a40)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:752 +0x118
github.com/gotranspile/cxgo.(*translator).convertAndExpr(0x1400040ca00, 0x14000473ab0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:771 +0x158
github.com/gotranspile/cxgo.(*translator).convertLOrExcExpr(0x1400040ca00, 0x14000473b20)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:787 +0x158
github.com/gotranspile/cxgo.(*translator).convertLOrIncExpr(0x1400040ca00, 0x14000473b90)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:803 +0x158
github.com/gotranspile/cxgo.(*translator).convertLAndExpr(0x1400040ca00, 0x14000459320)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:819 +0x1a4
github.com/gotranspile/cxgo.(*translator).convertLOrExpr(0x1400040ca00, 0x14000459380)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:832 +0x1a4
github.com/gotranspile/cxgo.(*translator).convertCondExpr(0x1400040ca00, 0x14000470c60)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:845 +0x1c4
github.com/gotranspile/cxgo.(*translator).convertAssignExpr(0x1400040ca00, 0x14000470cf0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:1134 +0x218
github.com/gotranspile/cxgo.(*translator).convertExprStmt(0x1400040ca00, 0x14000466740)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:1203 +0x168
github.com/gotranspile/cxgo.(*translator).convertStmt(0x1400040ca00, 0x140004653b0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:1355 +0x54
github.com/gotranspile/cxgo.(*translator).convertCompStmt(0x1400040ca00, 0x14000468270)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:616 +0x90
github.com/gotranspile/cxgo.(*translator).convertCompBlockStmt(0x1400040ca00, 0x14000468270)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:626 +0x30
github.com/gotranspile/cxgo.(*translator).convertFuncDef(0x1400040ca00, 0x140004681a0)
        /Users/jarrettkuklis/GolandProjects/cxgo/convert.go:127 +0x1e8
github.com/gotranspile/cxgo.(*translator).translateC(0x1400040ca00, {0x16b167b4f, 0x2b}, 0x14000460900)
        /Users/jarrettkuklis/GolandProjects/cxgo/translate.go:311 +0x174
github.com/gotranspile/cxgo.(*translator).translate(0x1400040ca00, {0x16b167b4f, 0x2b}, 0x14000460900)
        /Users/jarrettkuklis/GolandProjects/cxgo/translate.go:260 +0x40
github.com/gotranspile/cxgo.TranslateAST({0x16b167b4f, 0x2b}, 0x14000460900, 0x14000246300, {{0x0, 0x0}, {0x105043b8c, 0x4}, {0x14000220120, 0x2c}, ...})
        /Users/jarrettkuklis/GolandProjects/cxgo/translate.go:156 +0x70
github.com/gotranspile/cxgo.Translate({0x0, 0x0}, {0x16b167b4f, 0x2b}, {0x14000220120, 0x24}, 0x14000246300, {{0x0, 0x0}, {0x105043b8c, ...}, ...})
        /Users/jarrettkuklis/GolandProjects/cxgo/translate.go:74 +0x194
main.init.0.func1(0x14000236780, {0x14000210930, 0x1, 0x1})
        /Users/jarrettkuklis/GolandProjects/cxgo/cmd/cxgo/file.go:40 +0x178
github.com/spf13/cobra.(*Command).execute(0x14000236780, {0x14000210900, 0x1, 0x1})
        /Users/jarrettkuklis/go/pkg/mod/github.com/spf13/[email protected]/command.go:826 +0x668
github.com/spf13/cobra.(*Command).ExecuteC(0x1053fde40)
        /Users/jarrettkuklis/go/pkg/mod/github.com/spf13/[email protected]/command.go:914 +0x344
github.com/spf13/cobra.(*Command).Execute(...)
        /Users/jarrettkuklis/go/pkg/mod/github.com/spf13/[email protected]/command.go:864
main.main()
        /Users/jarrettkuklis/GolandProjects/cxgo/cmd/cxgo/main.go:63 +0x30

Process finished with the exit code 2

Convert defines to constants when possible

It's typical to have constants defined with #define.

cxgo should recognize those patterns and declare the corresponding constant in Go.

Unfortunately last time I checked, cc had no info for macro expansion. Need to double-check this and possibly contribute support, if it's not there yet.

Panic during libc.Realloc

I noticed that my project was randomly crashing from time to time with a panic similar to the following:

unexpected fault address 0xc00017ffe0
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0xc00017ffe0 pc=0xc797b7]

goroutine 1 [running]:
runtime.throw({0xca46bd?, 0x0?})
        C:/Program Files/Go/src/runtime/panic.go:992 +0x76 fp=0xc000071eb0 sp=0xc000071e80 pc=0xc50d76
runtime.sigpanic()
        C:/Program Files/Go/src/runtime/signal_windows.go:261 +0x125 fp=0xc000071ef8 sp=0xc000071eb0 pc=0xc620a5
runtime.memmove()
        C:/Program Files/Go/src/runtime/memmove_amd64.s:512 +0x657 fp=0xc000071f00 sp=0xc000071ef8 pc=0xc797b7
github.com/gotranspile/cxgo/runtime/libc.MemCpy(...)
        C:/Users/Crazyinfin8/go/pkg/mod/github.com/gotranspile/[email protected]/runtime/libc/string.go:120
github.com/gotranspile/cxgo/runtime/libc.Realloc(0xc00000e1e8, 0x1312d00)
        C:/Users/Crazyinfin8/go/pkg/mod/github.com/gotranspile/[email protected]/runtime/libc/memory.go:45 +0xd4 fp=0xc000071f40 sp=0xc000071f00 pc=0xc8efb4
main.main()
        C:/Users/Crazyinfin8/Desktop/mpg-go/realloc/main.go:10 +0x79 fp=0xc000071f80 sp=0xc000071f40 pc=0xc8f239
runtime.main()
        C:/Program Files/Go/src/runtime/proc.go:250 +0x1fe fp=0xc000071fe0 sp=0xc000071f80 pc=0xc5337e
runtime.goexit()
        C:/Program Files/Go/src/runtime/asm_amd64.s:1571 +0x1 fp=0xc000071fe8 sp=0xc000071fe0 pc=0xc78341
exit status 2

Doing some investigation, I managed to pinpoint the issue was with the function Realloc from the package github.com/gotranspile/cxgo/runtime/libc. In doing so, I created a small case that appears to reliably reproduce this panic on my Windows machine though for some odd reason, this does not create any panics on Windows Subsystem for Linux.

package main

import "github.com/gotranspile/cxgo/runtime/libc"

func main() {
	ptr := libc.Malloc(1)

	println("Original Pointer is: ", ptr)

	newPtr := libc.Realloc(ptr,20_000_000) // This panics sometimes

	if newPtr == nil {
		println("newPtr is nil")
	} else {
		println("New Pointer is: ", newPtr)
	}
}

I suspect the cause of this issue is that during the call to Realloc, it creates a new, bigger buffer. Then Realloc calls MemCpybut it converts both the original buffer and the new buffer as slices that are the size of the bigger buffer. This ends up making the call to Go's internal copy function try to read more bytes than the original buffer is supposed to have access to, leading to a potential panic.

Dependencies problem

maze.io/x/math32 - looks broken
Downloading failed with timeout
It isn't the problem of cxgo per se ,
just FYI
Thanks

panic in cxgo/convert.go

panic: types.ArrayType{elem:(*types.namedType)(0xc0000e2f30), size:1, slice:false}."name" (test.c:14:10)

struct s {
	const char *const name;		
};

static const struct s ss[] = {
	{NULL  },	
};


int
main(void) {

	if(!ss->name)
	 	return(-1);

 	return 0;
}	

Bitfields

Currently cxgo ignores information about bit sizes of fields. Should be supported at some point if we want to transpile ~anything that touches the disk/network.

cast to void produces wrong code

the following c code:

int a = 0;
(void)a;

should produce:

var a int = 0
_ = a

instead, it produces:

var a int = 0
a 

which doesn't compile in go because the variable is evaluated but not used

Compile fails for Nuklear

$ cat nuklear.c
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT

#include "nuklear.h"

nuklear.h is from https://github.com/Immediate-Mode-UI/Nuklear/blob/master/nuklear.h

Output of cxgo file nuklear.c

Error: parsing failed: nuklear.h:428:1: front-end: undefined: size_t
nuklear.h:429:1: front-end: undefined: size_t
nuklear.h:430:1: front-end: undefined: size_t
nuklear.h:431:1: front-end: undefined: size_t
nuklear.h:432:1: front-end: undefined: size_t

Goto forbidden by Go

Go has more strict rules regarding what goto jumps are valid.

cxgo currently doesn't reflow goto automatically. So "bad" goto will fail to compile in Go.

There is a workaround implemented in cxgo as one of the "ugly" ways to make the code compile. This workaround will completely flatten the code in a specified function.

We can try to implement a proper reflow algorithm, since those kind of goto statements are quite common.

C++ support

Although it would be really awesome to have C++ support, we don't plan to support C++ yet.

We do believe that full C support will eventually help us bootstrap C++ support (by converting GCC, for example), but that requires a ton of work.

So please do not file new issues or questions about C++ code... Unless you are ready to bootstrap C++ support yourself ๐Ÿ˜‰

Adding reaction here is welcome though. It will us help prioritize the conversion of GCC.

Proper layout for unions

Currently union layout is ignored. Instead fields are flattened into the parent structure.

Proper layout should be implemented at some point if we want to transpile ~anything that touches the disk/network.

Thread Local Storage

cxgo doesn't support thread local storage yet.

We can emulate it by passing a *TLS object to all the functions that use it, and to all their callers, similar to how context.Context is passed in Go.

Packed structs

Currently cxgo ignores __attribute__((__packed__)) . We should support it eventually, if we want to transpile anything that touches disk/network.

unsafe.Add for arrays

Do we want to start using unsafe.Add for arrays? It will make the code shorter and potentially easier to read. It would, however, require that we push the version of the compiler to 1.17 and all resulting code would use that version too.
Example:

var Ptr *int
Ptr = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(Ptr)) + uintptr(Len)))

Now becomes:

var Ptr *int
Ptr = (*int)(unsafe.Add(unsafe.Pointer(Ptr)), Len)

Label variables

C allows to take addresses of goto labels.

cxgo doesn't yet support label variables, however it should be possible to emulate.

Example of using cxgo to transpile physac 2d physics engine

Hi. I've found cxgo today and I think it's really exciting!

I decided to try to find some small project in C which might be interesting to be transpiled to go and this experiment was really successful. The project I found was Physac. It's a small 2d physics engine written in pure C with just a few deps.

I created a repo with end results of my try: https://github.com/koteyur/physac-go
In the first commit output is almost what I get after running cxgo. To make it usable I've just replaced time functions from libc package, because some of them wasn't implemented. After that it started working just fine.

TLDR; I think, this example of completely working program after using cxgo might be interesting.

Thanks!

fail with cygwin

cxgo
2022/02/17 07:31:29 clonning https://github.com/skyrpex/potrace.git to C:\cygwin
64\tmp\potrace
Cloning into 'C:\cygwin64\tmp\potrace'...
remote: Enumerating objects: 151, done.
remote: Counting objects: 100% (151/151), done.
remote: Compressing objects: 100% (123/123), done.
remote: Total 151 (delta 28), reused 69 (delta 26), pack-reused 0
Receiving objects: 100% (151/151), 648.91 KiB | 1.03 MiB/s, done.
Resolving deltas: 100% (28/28), done.
Note: switching to 'd32fc5acc2b53b14d0b682cee8c641320fb1ef44'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

git switch -c

Or undo this operation with:

git switch -

Turn off this advice by setting config variable advice.detachedHead to false

2022/02/17 07:31:31 writing to D:\code\cxgo-main.examples\potrace-go
2022/02/17 07:31:31 auxiliary.h
Error: auxiliary.h: parsing failed: C:\cygwin64\tmp\potrace\src\auxiliary.h:15:1
: include file not found: stdlib.h (wd D:\code\cxgo-main\examples\potrace)
search paths:
C:\cygwin64\tmp\potrace\src\includes
C:\cygwin64\tmp\potrace\src\include
/_cxgo_overrides
cxgo_predef.h:2:1: include file not found: cxgo_builtin.h (wd D:\code\cxgo-main
examples\potrace)
search paths:
C:\cygwin64\tmp\potrace\src\includes
C:\cygwin64\tmp\potrace\src\include
/_cxgo_overrides
Usage:
cxgo [flags]
cxgo [command]

Available Commands:
completion Generate the autocompletion script for the specified shell
file transpile a single C file to Go
help Help about any command
version print cxgo version

Flags:
-c, --config string config file path (default "cxgo.yml")
-h, --help help for cxgo

Use "cxgo [command] --help" for more information about a command.

auxiliary.h: parsing failed: C:\cygwin64\tmp\potrace\src\auxiliary.h:15:1: inclu
de file not found: stdlib.h (wd D:\code\cxgo-main\examples\potrace)
search paths:
C:\cygwin64\tmp\potrace\src\includes
C:\cygwin64\tmp\potrace\src\include
/_cxgo_overrides
cxgo_predef.h:2:1: include file not found: cxgo_builtin.h (wd D:\code\cxgo-main
examples\potrace)
search paths:
C:\cygwin64\tmp\potrace\src\includes
C:\cygwin64\tmp\potrace\src\include
/_cxgo_overrides

Return Statement Reachability

Possibly related to #10

Go enforces a syntactic reachability analysis for returns, while C never required that returns be reachable and C compilers which do reachability use more sophisticated algorighms.
Some situations where the return statement is considered reachable (or at least not an issue) by C are not considered reachable by Go.

It appears that cxgo has implemented a bit of checking to implicitly add missing returns (see postproc.go:fixImplicitReturnStmts).
However, I've found a test case which is improperly handled.

#include <stdio.h>

#define TRUE 1
#define FALSE 0

int implicit_return(char* str)
{
    while(TRUE)
    {
        while(TRUE)
        {
            if(*str == '\0') { return 0; }
            else if(*str != 'a') { break; }
            str++;
        }

        printf("%c is not a\n", *str);
        str++;
    }
}

int main()
{
    return implicit_return("aaabaababaaaaa");
}

I believe the last line of this function should have an (actually unreachable) return 0 added to fool Go into believing there is a reachable return 0.

DISTRIBUTION STATEMENT โ€œAโ€. (Approved for public release. Distribution is unlimited.)

This material is based upon work supported by DARPA under Contract No. HR001122C0047. Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of DARPA. DISTRIBUTION STATEMENT โ€œAโ€. (Approved for public release. Distribution is unlimited.)

Document intended use case

One thing that is missing from the project goals section in the documentation is the target use case. The use case makes a huge difference in how you approach the task of transpiling C to Go. Consider the difference between github.com/rsc/c2go (use case: convert Go compiler and runtime to Go, and leave the C version behind) and modernc.org/ccgo (use case: call C libraries, like sqlite, from Go without using CGo).

I found this much explanation of the use case in a Reddit comment:

The main idea for this project was to have cxgo download the latest commit, transpile it, and then push it to the go repo. Then by hand a developer can write an idiomatic and stable api on top of that others can use. This way future updates to the c project can be incorporated by just running the tool again.

So the use case appears to be basically in the "call C libraries without CGo" camp.

panic: interface conversion: types.Type is types.IntType, not *types.StructType

I tried to transpile some C source from this project.

Getting this panic:

/Users/prologic/tmp/genext2fs # cxgo file genext2fs.c
panic: interface conversion: types.Type is types.IntType, not *types.StructType

goroutine 1 [running]:
github.com/gotranspile/cxgo.(*translator).convertStructType.func1()
	/go/pkg/mod/github.com/gotranspile/[email protected]/c_type.go:357 +0x6bd
github.com/gotranspile/cxgo.(*translator).newOrFindNamedType(0xc001932840, {0xc0000b4558, 0x8}, 0xc000fbfd98)
	/go/pkg/mod/github.com/gotranspile/[email protected]/c_type.go:149 +0x8e
github.com/gotranspile/cxgo.(*translator).convertStructType(0xc001932840, {{0x0, 0x0}, 0x0, {0x0, 0x0}, 0x0, {0x0, 0x0}, 0x0, ...}, ...)
	/go/pkg/mod/github.com/gotranspile/[email protected]/c_type.go:389 +0x275
github.com/gotranspile/cxgo.(*translator).newTypeCC(0xc001932840, {{0x0, 0x0}, 0x0, {0x0, 0x0}, 0x0, {0x0, 0x0}, 0x0, ...}, ...)
	/go/pkg/mod/github.com/gotranspile/[email protected]/c_type.go:241 +0x618
github.com/gotranspile/cxgo.(*translator).convertType(0xc001932840, {{0x0, 0x0}, 0x0, {0x0, 0x0}, 0x0, {0x0, 0x0}, 0x0, ...}, ...)
	/go/pkg/mod/github.com/gotranspile/[email protected]/c_type.go:59 +0x3c5
github.com/gotranspile/cxgo.(*translator).convertDecl(0xc001932840, 0xc000198640)
	/go/pkg/mod/github.com/gotranspile/[email protected]/convert.go:391 +0x24f8
github.com/gotranspile/cxgo.(*translator).translateC(0xc001932840, {0x7ffcd8a76f0c?, 0xc0000bcc60?}, 0xc0017cf080)
	/go/pkg/mod/github.com/gotranspile/[email protected]/translate.go:320 +0x133
github.com/gotranspile/cxgo.(*translator).translate(0xc001932840, {0x7ffcd8a76f0c, 0xb}, 0x4?)
	/go/pkg/mod/github.com/gotranspile/[email protected]/translate.go:267 +0x4b
github.com/gotranspile/cxgo.TranslateAST({0x7ffcd8a76f0c, _}, _, _, {{0x0, 0x0}, {0x876f27, 0x4}, {0xc0000b4810, 0xc}, ...})
	/go/pkg/mod/github.com/gotranspile/[email protected]/translate.go:163 +0x98
github.com/gotranspile/cxgo.Translate({0x0, _}, {_, _}, {_, _}, _, {{0x0, 0x0}, {0x876f27, ...}, ...})
	/go/pkg/mod/github.com/gotranspile/[email protected]/translate.go:77 +0x233
main.init.0.func1(0xc0000b6780?, {0xc000098870?, 0x1?, 0x1?})
	/go/pkg/mod/github.com/gotranspile/[email protected]/cmd/cxgo/file.go:40 +0x19a
github.com/spf13/cobra.(*Command).execute(0xc0000b6780, {0xc000098840, 0x1, 0x1})
	/go/pkg/mod/github.com/spf13/[email protected]/command.go:826 +0x67c
github.com/spf13/cobra.(*Command).ExecuteC(0xb765c0)
	/go/pkg/mod/github.com/spf13/[email protected]/command.go:914 +0x2ee
github.com/spf13/cobra.(*Command).Execute(...)
	/go/pkg/mod/github.com/spf13/[email protected]/command.go:864
main.main()
	/go/pkg/mod/github.com/gotranspile/[email protected]/cmd/cxgo/main.go:63 +0x25
/Users/prologic/tmp/genext2fs #

To reproduce:

$ git clone https://github.com/bestouff/genext2fs.git
$ docker run -i -t --rm -v $PWD:$PWD -w $PWD golang:alpine /bin/sh
# apk add musl-dev
# ln -s /usr/include .
# go install github.com/gotranspile/cxgo/cmd/cxgo@latest
# cxgo file genext2fs.c

Support typed nil values

Currently cxgo fails on Nuklear due to the fact that we erase types for nil values:

typedef int ptrdiff_t;
#define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
int a = NK_ALIGNOF(int);

RAND_MAX missing

One of the c projects I am trying to convert uses RAND_MAX found in stdlib.h. I added it to the header in libs/stdlib.go and a go constant in runtime/libc/rand.go. I wondered if there is a way to make the header define equal to the go constant? This way future changes don't require two places to be updated.

Handle struct vs function name collisions

In C it's valid to have struct foo defined alongside with void foo(). When using cxgo this causes name collision.

We should detect this case and append _t to a converted Go type name automatically.

assigning string to [] of custom type fails

#include <stdint.h>
int main() {
	typedef uint8_t  MYubyte;
	MYubyte vendor[] = "Robert Winkler";
	return 0;
}

This code compiles under gcc but it doesn't in cxgo. I get this error:
Error: parsing failed: test.c:4:21: initializer for an object that has aggregate or union type shall be a brace-enclosed list of initializers for the elements or named members: array of MYubyte

Support static specifier

Currently static specifier is ignored, leading to incorrect code (variable is defined in the local scope, with the lifetime of a block).

This is a serious issue and it must be addressed.

Missing Functions on Windows

When I did go get -u github.com/gotranspile/cxgo/cmd/cxgo on my windows computer. This is what was happened:

go: downloading modernc.org/cc/v3 v3.33.9
# github.com/gotranspile/cxgo/runtime/csys
D:\go\pkg\mod\github.com\gotranspile\[email protected]\runtime\csys\ioctl.go:22:30: not enough arguments in call to syscall.Syscall
D:\go\pkg\mod\github.com\gotranspile\[email protected]\runtime\csys\ioctl.go:22:31: undefined: syscall.SYS_IOCTL
# github.com/gotranspile/cxgo/runtime/cnet
D:\go\pkg\mod\github.com\gotranspile\[email protected]\runtime\cnet\socket.go:52:21: cannot use fd (type int) as type syscall.Handle in argument to syscall.Bind
D:\go\pkg\mod\github.com\gotranspile\[email protected]\runtime\cnet\socket.go:68:2: cannot use fd (type syscall.Handle) as type int in return argument
D:\go\pkg\mod\github.com\gotranspile\[email protected]\runtime\cnet\socket.go:103:30: cannot use fd (type int) as type syscall.Handle in argument to syscall.SetsockoptInt

This is because the syscall package is used which is different for each OS.

inner struct doesn't generate

Given the following C code:

struct hello {
  struct inside {
    int x;
  } stuff;
};

I get this Go code:

package main

type hello struct {
	Stuff inside
}

It doesn't generate the inside struct.

including sys/socket.h panics

Just including sys/socket.h causes a panic:

#include <sys/socket.h>

int main() {
  inet_addr("...");
  return 0;
}

I confirmed that arpa/inet.h is being registered in registery.go. I'm not sure the difference between Env.GetLibrary and Env.GetLib.

panic: cannot find library: arpa/inet.h

goroutine 38 [running]:
github.com/gotranspile/cxgo/libs.(*Env).GetLib(...)
        /Users/jarrettkuklis/GolandProjects/cxgo/libs/config.go:58
github.com/gotranspile/cxgo/libs.init.29.func1(0xc000140320, 0xc000114c60)
        /Users/jarrettkuklis/GolandProjects/cxgo/libs/sys_socket.go:20 +0x3211
github.com/gotranspile/cxgo/libs.(*Env).GetLibrary(0xc000140320, 0xc00002a051, 0xc, 0xc00039c601, 0xc00039e2a8)
        /Users/jarrettkuklis/GolandProjects/cxgo/libs/registry.go:140 +0xe2
github.com/gotranspile/cxgo/libs.(*Env).NewLibrary(0xc000140320, 0xc00002a040, 0x1d, 0xc0001e3938, 0x10ad98d)
        /Users/jarrettkuklis/GolandProjects/cxgo/libs/registry.go:193 +0xcf
github.com/gotranspile/cxgo.includeFS.content(0xc000140320, 0xc00002a040, 0x1d, 0xc00039c601, 0xc0001e3978, 0xc0001e3978, 0x10a6707, 0x1585b60)
        /Users/jarrettkuklis/GolandProjects/cxgo/vfs.go:28 +0x4c
github.com/gotranspile/cxgo.includeFS.Stat(0xc000140320, 0xc00002a040, 0x1d, 0xc000110001, 0x1, 0x0, 0x1585d20, 0xc00039c660)
        /Users/jarrettkuklis/GolandProjects/cxgo/vfs.go:36 +0x52
modernc.org/cc/v3.overlayFS.Stat(0x15891b0, 0x1805848, 0x1589138, 0xc000140320, 0xc00002a040, 0x1d, 0x1, 0x0, 0x1d, 0xc00002a040, ...)
        /Users/jarrettkuklis/go/pkg/mod/modernc.org/cc/[email protected]/filesystem.go:87 +0x13b
modernc.org/cc/v3.(*context).statFile(0xc000104600, 0xc00002a040, 0x1d, 0xc00002a001, 0x1d, 0x0, 0x1585b60, 0xc000110030)
        /Users/jarrettkuklis/go/pkg/mod/modernc.org/cc/[email protected]/cc.go:769 +0x5e
modernc.org/cc/v3.(*ppIncludeDirective).translationPhase4(0xc00015c740, 0xc00015a840)
        /Users/jarrettkuklis/go/pkg/mod/modernc.org/cc/[email protected]/cpp.go:2462 +0xa6c
modernc.org/cc/v3.(*ppFile).translationPhase4(0xc000140440, 0xc00015a840)
        /Users/jarrettkuklis/go/pkg/mod/modernc.org/cc/[email protected]/cpp.go:3029 +0xa3
modernc.org/cc/v3.(*cpp).translationPhase4.func2(0xc00015a840, 0xc000140480, 0x2, 0x2)
        /Users/jarrettkuklis/go/pkg/mod/modernc.org/cc/[email protected]/cpp.go:2598 +0x1b2
created by modernc.org/cc/v3.(*cpp).translationPhase4
        /Users/jarrettkuklis/go/pkg/mod/modernc.org/cc/[email protected]/cpp.go:2586 +0x126

Question regarding defines

Before opening of NI , i send the same information to community (gotranspile/community room)
Looks not active since dec 2022

Because all examples failed on my computer (different reasons), I tried to check simple single file:

    #include <stdlib.h>
    #include <errno.h>
    void main() {
        errno = ENOMEM;
    }

cxgo file main.c

creates :

package main

import "github.com/gotranspile/cxgo/runtime/libc"

func main() {
    libc.Errno = ENOMEM
}

go build main.go returns error:

./main.go:6:15: undefined: ENOMEM

I expected that RegisterLibrary("errno.h",... will replace ENOMEM or add const to go file

This problem was solved using replace:
package: main
int_size: 8
ptr_size: 8
use_go_int: true
files:
name: main.c
replace:
old: 'ENOMEM'
new: '50'

What is the right way?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.