diff --git a/cl/_testmockc/type/in.h b/cl/_testmockc/type/in.h new file mode 100644 index 00000000..1c6e0336 --- /dev/null +++ b/cl/_testmockc/type/in.h @@ -0,0 +1,3 @@ +int sort(void* a, void* b, int elementSize, int count, int (*cmp)(const void*, const void*)); + +void g(void); diff --git a/cl/_testmockc/type/out.go b/cl/_testmockc/type/out.go new file mode 100644 index 00000000..05977c2e --- /dev/null +++ b/cl/_testmockc/type/out.go @@ -0,0 +1,12 @@ +package foo + +import ( + "github.com/goplus/lib/c" + "unsafe" +) + +//go:linkname Sort C.sort +func Sort(a unsafe.Pointer, b unsafe.Pointer, elementSize c.Int, count c.Int, cmp func(_llcppg_param1 unsafe.Pointer, _llcppg_param2 unsafe.Pointer) c.Int) c.Int + +//go:linkname G C.g +func G() diff --git a/cl/blockctx.go b/cl/blockctx.go index a819963d..2726aae6 100644 --- a/cl/blockctx.go +++ b/cl/blockctx.go @@ -99,13 +99,9 @@ func (p *blockCtx) initFile(file Source) { p.file.SetLinesForContent(src) } -func (p *blockCtx) getPubName(pfnName *string) (rewritten bool) { - fnName := *pfnName - pubName := cPubName(fnName) +func (p *blockCtx) getPubName(fnName string) (pubName string, rewritten bool) { + pubName = cPubName(fnName) rewritten = fnName != pubName - if rewritten { - *pfnName = pubName - } return } diff --git a/cl/compile.go b/cl/compile.go index 4bf179f0..b09e9393 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -172,31 +172,16 @@ func compileFunc(ctx *blockCtx, fn clang.Cursor) { return } - fnName := clang.String(fn) + origName := clang.String(fn) if debugCompileDecl { - log.Println("func", fnName, "-", clang.String(fn.Type())) - } - origName := fnName - rewritten := ctx.getPubName(&fnName) - n := fn.NumArguments() - var params []*types.Var - var results *types.Tuple - for i := range n { - item := fn.Argument(c.Uint(i)) - param := newParam(ctx, item, i) - params = append(params, param) - } - variadic := fn.IsVariadic() != 0 - if variadic { - params = append(params, newVariadicParam(ctx)) + log.Println("func", origName, "-", clang.String(fn.Type())) } pkg := ctx.pkg - retType := fn.ResultType() - if retType.Kind != lc.TypeVoid { - tyRet := toType(ctx, retType, flagRetType) - results = types.NewTuple(pkg.NewParam(token.NoPos, "", tyRet, false)) - } - sig := types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), results, variadic) + pkgTypes := pkg.Types + fnName, rewritten := ctx.getPubName(origName) + params, variadic := newParams(ctx, pkgTypes, fn) + results := toFuncResults(ctx, pkgTypes, fn.ResultType()) + sig := types.NewSignatureType(nil, nil, nil, params, results, variadic) f, err := pkg.NewFuncWith(goNodePos(ctx, fn), fnName, sig, nil) if err != nil { log.Panicln("compileFunc:", fnName, err) @@ -213,27 +198,35 @@ func compileFunc(ctx *blockCtx, fn clang.Cursor) { } } -var ( - tyValist types.Type = types.NewSlice(gogen.TyAny) -) - -func newVariadicParam(ctx *blockCtx) *types.Var { - return types.NewParam(token.NoPos, ctx.pkg.Types, "__llgo_va_list", tyValist) +func newParams(ctx *blockCtx, pkg *types.Package, fn clang.Cursor) (ret *types.Tuple, variadic bool) { + n := fn.NumArguments() + var params []*types.Var + for i := range n { + item := fn.Argument(c.Uint(i)) + param := newParam(ctx, pkg, item, i) + params = append(params, param) + } + variadic = fn.IsVariadic() != 0 + if variadic { + params = append(params, newVariadicParam(pkg)) + } + ret = types.NewTuple(params...) + return } -func newParam(ctx *blockCtx, decl clang.Cursor, i c.Int) *types.Var { +func newParam(ctx *blockCtx, pkg *types.Package, decl clang.Cursor, i c.Int) *types.Var { declName := clang.String(decl) declTyp := decl.Type() if debugCompileDecl { log.Println(" => param", declName, "-", clang.String(declTyp)) } - typ := toType(ctx, declTyp, flagIsParam) + typ := toType(ctx, pkg, declTyp, flagIsParam) if declName != "" { avoidKeyword(&declName) } else { declName = "_llcppg_param" + strconv.Itoa(int(i)+1) } - return types.NewParam(goNodePos(ctx, decl), ctx.pkg.Types, declName, typ) + return types.NewParam(goNodePos(ctx, decl), pkg, declName, typ) } // ----------------------------------------------------------------------------- diff --git a/cl/type_and_var.go b/cl/type_and_var.go index 3b348136..0286aea2 100644 --- a/cl/type_and_var.go +++ b/cl/type_and_var.go @@ -20,8 +20,10 @@ import ( "go/token" "go/types" "log" + "strconv" "github.com/goplus/gogen" + "github.com/goplus/lib/c" "github.com/goplus/llcppg/clang" lc "github.com/goplus/llcppg/lib/clang" ) @@ -60,7 +62,7 @@ func newPointer(typ types.Type) types.Type { return types.NewPointer(typ) } -func toType(ctx *blockCtx, typ lc.Type, flags int) types.Type { +func toType(ctx *blockCtx, pkg *types.Package, typ lc.Type, flags int) types.Type { switch typ.Kind { case lc.TypeCharS: return ctx.c.Ref("Char").Type() @@ -69,14 +71,59 @@ func toType(ctx *blockCtx, typ lc.Type, flags int) types.Type { case lc.TypeUInt: return ctx.c.Ref("Uint").Type() case lc.TypePointer: - pointee := toType(ctx, typ.PointeeType(), flags) + elem := typ.PointeeType() + if elem.Kind == lc.TypeFunctionProto { + return toFuncType(ctx, pkg, elem) + } + pointee := toType(ctx, pkg, elem, flags) return newPointer(pointee) + case lc.TypeVoid: + return tyVoid default: log.Println("==> toType: unknown Kind -", typ.Kind) } panic("todo: toType " + clang.String(typ)) } +func toFuncType(ctx *blockCtx, pkg *types.Package, fn lc.Type) *types.Signature { + params, variadic := toFuncParams(ctx, pkg, fn) + results := toFuncResults(ctx, pkg, fn.ResultType()) + return types.NewSignatureType(nil, nil, nil, params, results, variadic) +} + +func toFuncParams(ctx *blockCtx, pkg *types.Package, fn lc.Type) (ret *types.Tuple, variadic bool) { + n := fn.NumArgTypes() + var params []*types.Var + for i := range n { + item := fn.ArgType(c.Uint(i)) + tyParam := toType(ctx, pkg, item, flagIsParam) + nameParam := "_llcppg_param" + strconv.Itoa(int(i)+1) + params = append(params, types.NewParam(token.NoPos, pkg, nameParam, tyParam)) + } + variadic = fn.IsFunctionTypeVariadic() != 0 + if variadic { + params = append(params, newVariadicParam(pkg)) + } + ret = types.NewTuple(params...) + return +} + +var ( + tyValist types.Type = types.NewSlice(gogen.TyAny) +) + +func newVariadicParam(pkg *types.Package) *types.Var { + return types.NewParam(token.NoPos, pkg, "__llgo_va_list", tyValist) +} + +func toFuncResults(ctx *blockCtx, pkg *types.Package, retType lc.Type) (results *types.Tuple) { + if retType.Kind != lc.TypeVoid { + tyRet := toType(ctx, pkg, retType, flagRetType) + results = types.NewTuple(types.NewParam(token.NoPos, pkg, "", tyRet)) + } + return +} + // ----------------------------------------------------------------------------- func substObj(pkg *types.Package, scope *types.Scope, origName string, real types.Object) {