Calling C Code with Automatic Differentiation in Julia

My naive attempt

julia> using Enzyme

julia> file = """
       double square(double x) {
           return x * x;
       }
       """;

julia> run(pipeline(`clang -x c - -fPIC -fembed-bitcode -shared -o libsquare.dylib`; stdin=IOBuffer(file)))
Process(`clang -x c - -fPIC -fembed-bitcode -shared -o libsquare.dylib`, ProcessExited(0))

julia> csquare(x::Cdouble) = @ccall "./libsquare.dylib".square(x::Cdouble)::Cdouble
csquare (generic function with 1 method)

julia> first(first(autodiff(Reverse, csquare, Active, Active(3.14))))
ERROR:
No reverse pass found for ejlstr$square$./libsquare.dylib
 at context:   %3 = call double @"ejlstr$square$./libsquare.dylib"(double %0) #5, !dbg !14

Stacktrace:
 [1] csquare
   @ ./REPL[16]:1

failed, so yeah, I hope they can provide a working example :slightly_smiling_face:

Edit: I found this thread Is it possible to use autodiff on an external program? - #2 by wsmoses which suggests the same strategy, but without a working example.

Edit 2: I managed not to get an error with

julia> using Enzyme, Libdl

julia> file = """
       double square(double x) {
           return x * x;
       }
       """;

julia> run(pipeline(`clang -x c - -fPIC -fembed-bitcode -shared -o libsquare.dylib`; stdin=IOBuffer(file)))
Process(`clang -x c - -fPIC -fembed-bitcode -shared -o libsquare.dylib`, ProcessExited(0))

julia> fptr = dlsym(dlopen("./libsquare.dylib"), :square)
Ptr{Nothing} @0x0000000104833f9c

julia> csquare(x::Cdouble) = ccall(fptr, Cdouble, (Cdouble,), x)
csquare (generic function with 1 method)

julia> first(first(autodiff(Reverse, csquare, Active, Active(3.14))))
0.0

but the result is still wrong, so I’m clearly still missing something.