Konstantin8105 / c4go

Transpiling C code to Go code
MIT License
365 stars 38 forks source link

Stdlib example from README #314

Closed im-kulikov closed 5 years ago

im-kulikov commented 5 years ago

In README we can see example:

#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;
}

that can be simplified to

package main

import (
    "fmt"
    "os"
)

func main() {
    var n, c int

    fmt.Print("Enter a number\n")
    // get value
    fmt.Scanf("%d", &n)
    fmt.Printf("The number is: %d\n", 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")
        }
    }
}

I do not quite understand the meaning of using unsafe and noarch packages in this case, when you can translate this code much easier.

@Konstantin8105, What you think?

Konstantin8105 commented 5 years ago

Yes, you are right. Main probrem - pointers. Now, general approach C pointers and C array transpile to Go slice with unsafe. So, it is not easy to use simplification like in your code. For that example , we can simplify and avoid package noarch. Feel free for PR. Result Go code is must build, must work but now look in Go way.

im-kulikov commented 5 years ago

Now, general approach C pointers and C array transpile to Go slice with unsafe

Can you provide example?

If you don't mind, I propose to don’t close the issue to continue the discussion and organize PR

Konstantin8105 commented 5 years ago

You have a good question. I don't remember, you can research this, but please remember about 2 operations(see next examples) and that operations will have unsafe always:

Just for example, please run:

 go test -v -tags=integration -run=TestIntegrationScripts/tests/array.c

and look in files: ~/go/src/github.com/Konstantin8105/c4go/tests/array.c ~/go/src/github.com/Konstantin8105/c4go/testdata/tests/array/main.go

Example of pointer arithmetic C:

float* next_pointer(float* v)
{
    long l = 1;
    long p = 2;
    (void)(l);
    (void)(p);
    return p - p + v + l;
}

Go:

// next_pointer - transpiled function from  C4GO/tests/array.c:178
func next_pointer(v []float32) []float32 {
    var l int32 = 1
    var p int32 = 2
    _ = (l)
    _ = (p)
    return (*(*[1000000000]float32)(unsafe.Pointer(uintptr(unsafe.Pointer(&(*(*[1000000000]float32)(unsafe.Pointer(uintptr(unsafe.Pointer(&v[0])) + (uintptr)(p-p)*unsafe.Sizeof(v[0]))))[:][0])) + (uintptr)(l)*unsafe.Sizeof((*(*[1000000000]float32)(unsafe.Pointer(uintptr(unsafe.Pointer(&v[0])) + (uintptr)(p-p)*unsafe.Sizeof(v[0]))))[:][0]))))[:]
}

or

absolute syntatic test - it is ok by C, but I don't finish for Go:

#include <stdio.h>

int global;

int * pd()
{
    global = 45;
    return &global;
}

int main() {
    int     *i  = pd();
    char    *c  = i;
    double  *d  = c;
    int     *i2 = d;
    printf("%d\n", *i2);
    return 0;
}

Go:

package main

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

var global int

// pd - transpiled function from  $GOPATH/src/templorary/wer/main.c:5
func pd() []int {
    global = 45
    return (*[100000000]int)(unsafe.Pointer(&global))[:]
}

// main - transpiled function from  $GOPATH/src/templorary/wer/main.c:11
func main() {
    var i []int = pd()
    var c []byte = i
    var d []float64 = c
    var i2 []int = d
    noarch.Printf([]byte("%d\n\x00"), i2[0])
    return
}

Also, you can use project https://github.com/elliotchance/c2go/ with another approach C array, C pointer -> Go unsafe.Pointer. Choose tool in according to your task. My point of view:

im-kulikov commented 5 years ago

Oh.. thanks a lot! I’ll try to make research

Konstantin8105 commented 5 years ago

This is a good example for your question:

#include <stdio.h>

void a(int *v1)
{
    printf("a: %d\n",*v1);
}

void b(int v1[], int size)
{
    for (int i = 0;i < size; i++) {
        printf("b: %d %d\n", i,  v1[i]);
    }
}

int main() {
    int i1 = 42;
    a(&i1);
    b(&i1, 1);

    int i2[] = {11,22};
    a(i2);
    b(i2,2);

    return 0;
}

Go

package main

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

// a - transpiled function from  $GOPATH/src/templorary/wer/main2.c:3
func a(v1 []int) {
    noarch.Printf([]byte("a: %d\n\x00"), v1[0])
}

// b - transpiled function from  $GOPATH/src/templorary/wer/main2.c:8
func b(v1 []int, size int) {
    {
        var i int
        for ; i < size; i++ {
            noarch.Printf([]byte("b: %d %d\n\x00"), i, v1[i])
        }
    }
}

// main - transpiled function from  $GOPATH/src/templorary/wer/main2.c:15
func main() {
    var i1 int = 42
    a((*[100000000]int)(unsafe.Pointer(&i1))[:])
    b((*[100000000]int)(unsafe.Pointer(&i1))[:], 1)
    var i2 []int = []int{11, 22}
    a(i2)
    b(i2, 2)
    return
}

C language is too flexibility.

im-kulikov commented 5 years ago

Wow! Thank you immensely!

Konstantin8105 commented 5 years ago

May be I will add that example in README.md for showing the main approach of this project. Have fun.

Konstantin8105 commented 5 years ago

Close, because discussion is not progress.