diff --git a/src/abi_export.jl b/src/abi_export.jl index c62e36f..ed6132e 100644 --- a/src/abi_export.jl +++ b/src/abi_export.jl @@ -10,6 +10,7 @@ function recursively_add_types!(types::Base.IdSet{DataType}, @nospecialize(T::Da while T.name === Ptr.body.name push!(types, T) T = T.parameters[1] # unwrap Ptr{...} + T === Nothing && return types T in types && return types end if T.name.module === Core && T ∉ C_friendly_types @@ -68,7 +69,8 @@ function field_name_json(@nospecialize(dt::DataType), field::Int) end function emit_pointer_info!(ctx::TypeEmitter, @nospecialize(dt::DataType); indent::Int = 0) - pointee_type_id = ctx.type_ids[dt.parameters[1]] + pointee = dt.parameters[1] + pointee_type_id = pointee === Nothing ? "null" : string(ctx.type_ids[pointee]) let indented_println(args...) = println(ctx.io, " " ^ indent, args...) indented_println("{") indented_println(" \"id\": ", ctx.type_ids[dt], ",") @@ -167,7 +169,8 @@ function emit_method_info!(ctx::TypeEmitter, method::Core.Method; indent::Int = println(ctx.io, i == length(sig.parameters) ? " }" : " },") end indented_println(" ],") - indented_println(" \"returns\": { \"type_id\": ", ctx.type_ids[rt], " }") + rt_type_id = rt === Nothing ? "null" : string(ctx.type_ids[rt]) + indented_println(" \"returns\": { \"type_id\": ", rt_type_id, " }") print(ctx.io, " " ^ indent, "}") end end @@ -211,7 +214,7 @@ function write_abi_metadata(io::IO) for T in sig.parameters[2:end] recursively_add_types!(types, T) end - recursively_add_types!(types, rt) + rt !== Nothing && recursively_add_types!(types, rt) end end diff --git a/test/cli.jl b/test/cli.jl index ce126c1..bb199c8 100644 --- a/test/cli.jl +++ b/test/cli.jl @@ -113,6 +113,30 @@ end # `Ptr{CTree{Float64}}` should refer (recursively) back to the original type id Ptr_CTree_Float64 = abi["types"][CVector_CTree_Float64["fields"][2]["type_id"]] @test Ptr_CTree_Float64["pointee_type_id"] == CTree_Float64_id + + # `return_void(x::Ptr{Cvoid}, y::Ptr{Ptr{Cvoid}})::Cvoid` + fn_void = abi["functions"][findfirst(f -> f["symbol"] == "return_void", abi["functions"])::Int] + @test fn_void["returns"]["type_id"] === nothing + # `Ptr{Cvoid}` + ptr_cvoid = abi["types"][findfirst(t -> t["id"] == fn_void["arguments"][1]["type_id"], abi["types"])::Int] + @test ptr_cvoid["kind"] == "pointer" + @test ptr_cvoid["pointee_type_id"] === nothing + # `Ptr{Ptr{Cvoid}}` + ptr_ptr_cvoid = abi["types"][findfirst(t -> t["id"] == fn_void["arguments"][2]["type_id"], abi["types"])::Int] + @test ptr_ptr_cvoid["kind"] == "pointer" + @test ptr_ptr_cvoid["pointee_type_id"] == ptr_cvoid["id"] + + # `return_void_ptr()::Ptr{Cvoid}` + fn_void_ptr = abi["functions"][findfirst(f -> f["symbol"] == "return_void_ptr", abi["functions"])::Int] + ret_ptr = abi["types"][findfirst(t -> t["id"] == fn_void_ptr["returns"]["type_id"], abi["types"])::Int] + @test ret_ptr["kind"] == "pointer" + @test ret_ptr["pointee_type_id"] === nothing + + # `return_void_ptr_ptr()::Ptr{Ptr{Cvoid}}` + fn_void_ptr_ptr = abi["functions"][findfirst(f -> f["symbol"] == "return_void_ptr_ptr", abi["functions"])::Int] + ret_ptr_ptr = abi["types"][findfirst(t -> t["id"] == fn_void_ptr_ptr["returns"]["type_id"], abi["types"])::Int] + @test ret_ptr_ptr["kind"] == "pointer" + @test ret_ptr_ptr["pointee_type_id"] == ret_ptr["id"] end @testset "CLI library privatize end-to-end" begin diff --git a/test/libsimple.jl b/test/libsimple.jl index 64126ff..0229b36 100644 --- a/test/libsimple.jl +++ b/test/libsimple.jl @@ -45,6 +45,10 @@ Base.@ccallable function countsame(list::Ptr{MyTwoVec}, n::Int32)::Int32 return count end +Base.@ccallable return_void(x::Ptr{Cvoid}, y::Ptr{Ptr{Cvoid}})::Cvoid = nothing +Base.@ccallable return_void_ptr()::Ptr{Cvoid} = Ptr{Cvoid}() +Base.@ccallable return_void_ptr_ptr()::Ptr{Ptr{Cvoid}} = Ptr{Ptr{Cvoid}}() + export countsame, copyto_and_sum # FIXME? varargs