transpiling C code to Go code
Clone or download
Permalink
Failed to load latest commit information.
.snapshots Add flag for transpiling with all outside structs (#223) Nov 12, 2018
ast change tab to spaces (#251) Nov 13, 2018
examples Comment move Above Stmts (#238) Nov 8, 2018
linux Fix argv local test (#157) Oct 3, 2018
noarch CSTD: stdlib.h : atexit (#103) Nov 8, 2018
preprocessor Clang without optimization (#213) Oct 16, 2018
program CSTD: stdlib.h : atexit (#103) Nov 8, 2018
tests summ of sizeof (#236) Nov 8, 2018
transpiler Ignore ast.VisibilityAttr in transpiling (#245) Nov 13, 2018
travis Add flag for transpiling with all outside structs (#223) Nov 12, 2018
types CallExpr: use util.NewCallExpr (#244) Nov 12, 2018
util CallExpr: use util.NewCallExpr (#244) Nov 12, 2018
version fix go:generate : version (#187) Oct 11, 2018
.codeclimate.yml configurate codeclimate Mar 28, 2018
.gitattributes remove travis scripts from github statistic Mar 28, 2018
.gitignore Code style (#224) Oct 25, 2018
.travis.yml Code style (#224) Oct 25, 2018
CODE_OF_CONDUCT.md minor (#192) Oct 12, 2018
LICENSE Adding Izyumov Konstantin as a major contributor (#521) Jan 3, 2018
README.md Comment move Above Stmts (#238) Nov 8, 2018
cli_test.go F: version (closes #42) (#176) Oct 10, 2018
codecov.yml Adding custom codecov file so that it doesnt fail when coverage goes … Apr 26, 2017
cstd_test.go Code style (#224) Oct 25, 2018
main.go Add flag for transpiling with all outside structs (#223) Nov 12, 2018
main_test.go Code style (#224) Oct 25, 2018
other_test.go Add demo in CSparse (#254) Nov 13, 2018

README.md

Build Status Go Report Card codecov GitHub license GoDoc Maintainability

A tool for transpiling C code to Go code.

Milestones of the project:

  1. Transpiling project GNU GSL.
  2. Transpiling project GTK+.

Notes:

Installation

c4go requires Go 1.10 or newer.

go get -u github.com/Konstantin8105/c4go

Usage example

# Change your location to the folder with examples:
cd $GOPATH/src/github.com/Konstantin8105/c4go/examples/

# Transpile one file from the C example folder:
c4go transpile prime.c

# Look at the result
nano prime.go

# Check the result:
go run prime.go
# Enter a number
# 13
# The number is: 13
# Prime number.

C code of file prime.c:

#include <stdio.h>

int main()
{
    int n, c;

    printf("Enter a number\n");
    // get value
    scanf("%d", &n);
    printf("The number is: %d\n", n);

    // -------
    if (n == 2)
        printf("Prime number.\n");
    else {
        for (c = 2; c <= n - 1; c++) {
            if (n % c == 0)
                break;
        }
        if (c != n)
            printf("Not prime.\n");
        else
            printf("Prime number.\n");
    }
    return 0;
}

Go code of file prime.go:

//
//	Package main - transpiled by c4go
//
//	If you have found any issues, please raise an issue at:
//	https://github.com/Konstantin8105/c4go/
//

package main

import "unsafe"
import "github.com/Konstantin8105/c4go/noarch"
import "fmt"

// main - transpiled function from  $GOPATH/src/github.com/Konstantin8105/c4go/examples/prime.c:3
func main() {
	var n int
	var c int
	fmt.Printf("Enter a number\n")
	// get value
	noarch.Scanf([]byte("%d\x00"), (*[100000000]int)(unsafe.Pointer(&n))[:])
	noarch.Printf([]byte("The number is: %d\n\x00"), n)
	if n == 2 {
		// -------
		fmt.Printf("Prime number.\n")
	} else {
		for c = 2; c <= n-1; c++ {
			if n%c == 0 {
				break
			}
		}
		if c != n {
			fmt.Printf("Not prime.\n")
		} else {
			fmt.Printf("Prime number.\n")
		}
	}
	return
}

C standard library implementation

            assert.h	       1/1	         100%
             ctype.h	     14/14	         100%
             errno.h	       0/1	           0%
             float.h	          	    undefined
            iso646.h	          	    undefined
            limits.h	          	    undefined
            locale.h	       0/3	           0%
              math.h	     40/58	          69%
            setjmp.h	       0/3	           0%
            signal.h	       0/3	           0%
            stdarg.h	       4/4	         100%
            stddef.h	       2/6	        33.3%
             stdio.h	     33/46	        71.7%
            stdlib.h	     33/47	        70.2%
            string.h	     12/24	          50%
              time.h	      8/15	        53.3%
             wchar.h	      0/68	           0%
            wctype.h	      0/22	           0%

Contributing

Feel free to submit PRs or open issues. Main information from: en.cppreference.com

Testing

By default, only unit tests are run with go test. You can also include the integration tests:

go test -tags=integration ./...

Integration tests in the form of complete C programs that can be found in the tests directory.

Integration tests work like this:

  1. clang compiles the C to a binary as normal.
  2. c4go converts the C file to Go.
  3. Both binaries are executed and the output is compared. All C files will contain some output so the results can be verified.

Note

Use lastest version of clang.

If you use Ubuntu, then use command like next for choose clang version:

sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-6.0 1000

Performance

Main time of transpilation takes clang, for example run:

go test -tags=integration -run=Benchmark -bench=. -benchmem

Result looks for example:

goos: linux
goarch: amd64
pkg: github.com/Konstantin8105/c4go
BenchmarkTranspile/Full-6         	       5	 274922964 ns/op	43046865 B/op	  379676 allocs/op
BenchmarkTranspile/GoCode-6       	      20	  86806808 ns/op	36577533 B/op	  308060 allocs/op
PASS

So, transpilation time is just 30% of full time. In my point of view no need of performance optimization, see Amdahl's law.

Example of performance analyse

Please run:

# Run cpuprofiling for sqlite transpilation example
time ./travis/sqlite.sh 

# Example of output:
#
# % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                 Dload  Upload   Total   Spent    Left  Speed
#100 2217k  100 2217k    0     0   235k      0  0:00:09  0:00:09 --:--:--  357k
#Archive:  /tmp/SQLITE/sqlite-amalgamation-3250200.zip
#   creating: /tmp/SQLITE/sqlite-amalgamation-3250200/
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/sqlite3ext.h  
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/sqlite3.c  
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/sqlite3.h  
#  inflating: /tmp/SQLITE/sqlite-amalgamation-3250200/shell.c  
#After transpiling shell.c and sqlite3.c together, have summary: 695 warnings.
#In file sqlite.go summary : 3 warnings in go build.
#Amount unsafe package using: 2902
#
#real	0m18.434s
#user	0m14.212s
#sys	0m1.434s

# Run profiler
go tool pprof ./testdata/cpu.out

For more information, see Profiling Go Programs.