c2go
c2go copied to clipboard
Support function pointers
C
int (*f)(int, int);
int add(int a, int b) {
return a + b;
}
int mul(int a, int b) {
return a * b;
}
int main() {
f = add;
int i = f(3,4);
f = mul;
int j = f(3,4);
return i + j;
}
Suggested Go
type F interface {
f(int, int) int
}
type Add struct {}
func (Add) f(a int, b int) int {
return a + b
}
type Mul struct {}
func (Mul) f(a int, b int) int {
return a * b
}
func main() {
var f F = Add{}
noarch.Printf([]byte("%d\n\x00"), f.f(3, 4))
f = Mul{}
noarch.Printf([]byte("%d\n\x00"), f.f(3, 4))
}
Now I need to find out how to get from C to Go. This may not cover all cases...
You should not need to create an interface. You can just convert the function pointer directly to it's equivalent type, for example:
int (*f)(int, int) -> func (int, int) int
void (*f)(float) -> func (float32)
To fix this you will just need to teach resolve.go
how to translate one to the other by replacing this code: https://github.com/elliotchance/c2go/blob/master/types/resolve.go#L219-L225
Within a single function pointer you can use the resolve to convert each data type (of the parameters and return).
I have the C example above working by hard-coding "int (int, int)" in a few places, hard-coding the Go AST... I now need to make it work with other return types and parameters.
The changes are affecting:
- transpiler/declarations: transpileVarDecl
- types/resolve: ResolveType
- util/goast: internalTypeToExpr
I will keep working on this.
Go output: (no c2go warnings)
package main
import "os"
type __int128_t int64
type __uint128_t uint64
var f func(a int, b int) int
func add(a int, b int) int {
return a + b
}
func mul(a int, b int) int {
return a * b
}
func main() {
__init()
f = add
var i int = f(3, 4)
f = mul
var j int = f(3, 4)
os.Exit(i + j)
}
func __init() {
}
@yulvil The output looks perfect. Did you manually write that or was that the output of c2go?
@elliotchance The Go file was generated by c2go. I only implemented the int (*) (int, int)
function pointer. I need to make it work with other arg/return types.
Work in progress:
- https://github.com/elliotchance/c2go/compare/master...yulvil:funcptr?expand=1
I am hoping to finish implementing this over the weekend.
@yulvil , Excuse, I found your message, but too later - I create PR. Excuse me again.
@elliotchance @Konstantin8105 I do no think that the functionality is complete. We should reopen this issue.
- Remove the "function pointers are not supported" warnings
https://github.com/elliotchance/c2go/blob/master/types/resolve.go#L226,L231
- Add tests where the function arg type is different than int.
TODO:
- Add resolve test cases
{"int (*)(int, float, double)", "func(int, float32, float64) int"},
{"double (*)(double, double)", "func(float64, float64) float64"},
{"void (*)()", "func()"},
{"void (*)(void)", "func()"},
{"void (*)(int)", "func(int)"},
{"void (*)(void *)", "func(interface{})"},
{"void (*)(char *)", "func([]byte)"},
{"void (*)(char **)", "func([][]byte)"},
{"void* (*)()", "func() interface{}"},
Example:
double (*f)(int, float, double);
double add (int a, float b, double c) {
return c;
}
double mul (int a, float b, double c) {
return c;
}
int main() {
f = add;
f(3, 4, 5);
f = mul;
return f(3, 4, 5);
}
Current go output (not compiling)
// Warning (BinaryOperator): {main.c 12 0 3 7 }: function pointers are not supported
// Warning (BinaryOperator): {main.c 12 0 3 7 }: function pointers are not supported
// Warning (CallExpr): {main.c 13 0 3 12 }: I couldn't find an appropriate Go type for the C type 'float32'.
// Warning (CallExpr): {main.c 13 0 3 12 }: I couldn't find an appropriate Go type for the C type 'float64'.
// Warning (BinaryOperator): {main.c 15 0 3 7 }: function pointers are not supported
// Warning (BinaryOperator): {main.c 15 0 3 7 }: function pointers are not supported
// Warning (CallExpr): {main.c 16 0 10 19 }: I couldn't find an appropriate Go type for the C type 'float32'.
// Warning (CallExpr): {main.c 16 0 10 19 }: I couldn't find an appropriate Go type for the C type 'float64'.
// Warning (ReturnStmt): {main.c 16 0 3 19 }: I couldn't find an appropriate Go type for the C type 'float64'.
package main
import "os"
type __int128_t int64
type __uint128_t uint64
type __builtin_ms_va_list []byte
var f func(int, float32, float64) float64
func add(a int, b float32, c float64) float64 {
return c
}
func mul(a int, b float32, c float64) float64 {
return c
}
func main() {
__init()
f = add
f(3, nil, nil)
f = mul
os.Exit(nil)
}
func __init() {
}
go build main.go
# command-line-arguments
./main.go:30:4: cannot use nil as type float32 in argument to f
./main.go:30:4: cannot use nil as type float64 in argument to f
./main.go:32:9: cannot use nil as type int in argument to os.Exit
Some of these larger tasks should really be multiple issues so that we can provide the functionality in useful stages. Especially when "done" isn't an absolute measurement. Also there will always be cases where some edge case is not covered.
Thanks for providing that information, I've reopened this issue. I'll be sure to pay attention to when issues should really be broken down to something more specific. That's my bad since I opened this issue originally.
Present output:
/*
Package main - transpiled by c2go version: v0.21.10 Zinc 2018-02-14
If you have found any issues, please raise an issue at:
https://github.com/elliotchance/c2go/
*/
package main
import "os"
var f func(int, float32, float64) float64
// add - transpiled function from /home/konstantin/go/src/templorary/6.c:3
func add(a int, b float32, c float64) float64 {
return c
}
// mul - transpiled function from /home/konstantin/go/src/templorary/6.c:7
func mul(a int, b float32, c float64) float64 {
return c
}
// main - transpiled function from /home/konstantin/go/src/templorary/6.c:11
func main() {
f = add
f(3, float32(4), float64(5))
f = mul
os.Exit(int(f(3, float32(4), float64(5))))
}
func init() {
}
That issue can be closed.