Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get SafeCfunction by @safe_cfunction on c++ side not working correctly #466

Open
SergeyStrGroup opened this issue Jan 15, 2025 · 2 comments

Comments

@SergeyStrGroup
Copy link

SergeyStrGroup commented Jan 15, 2025

Hi.
I discovered amazing functionality with SafeCfunction which i previously try to write on my own.
Its perfectly worked trough the julia, but not with c++.
What i'm trying to do is to get SafeCfunction and cast.

  jl_value_t *ret = jl_eval_string(R"(
      using CxxWrap
      sum(x,y) = x+y
      @safe_cfunction(sum, Cint, (Cint, Cint)))");
  
   auto cFunc = jlcxx::unbox<jlcxx::SafeCFunction>(ret);
  
  auto ptr = jlcxx::make_function_pointer<int(int, int)>(cFunc);
  std::cout << fPtr1(1, 2);

Signature checked correctly
( with swapped types in message:
for exmaple with wrong signature, for above code, as follows int(double, int) i got the following (types should be swapped):
Incorrect argument type for cfunction at position 1, expected: Float64, obtained: Int32 )

But void pointer stored inside SafeCfunction is broken and function call crash.

[96636] signal 11: SIGSEGV
in expression starting at none:0
crt_sig_handler at C:/workdir/src\signals-win.c:95
.text at D:\projects_sources\datababse\julia\build\app\embedding.exe (unknown line)

Is there some trick to build SafeCfunction from c++? (i could bind function to add SafeCfunction into some container which i access from c++, but why it isnt working directly )

Thanks

@SergeyStrGroup SergeyStrGroup changed the title Get SafeCfunction by @safe_cfunction on c++ not working correctly Get SafeCfunction by @safe_cfunction on c++ side not working correctly Jan 15, 2025
@SergeyStrGroup
Copy link
Author

SergeyStrGroup commented Jan 15, 2025

Obviously if i change ptr inside SafeCFunction which i got from julia -> everything work correct.
Because ptr inside is incorrect.
I finnaly watch julia code and my code isnt working because of this:

macro safe_cfunction(f, rt, args)
  return esc(:($(@__MODULE__).SafeCFunction(@cfunction($f, $rt, $args), $rt, [$(args.args...)])))
end

Only _SafeCFunction mirrored, but i get SafeCFunction. Thats why arguments checked correctly.

So i add my version of macro as follows

 macro safe_cfunction_cpp(f, rt, args)
   return esc(:($(@__MODULE__).CxxWrap.CxxWrapCore._SafeCFunction(@cfunction($f, $rt, $args), $rt, [$(args.args...)])))
 end

Dont get about cconverter which should do exactly what i need, yet.

@barche
Copy link
Collaborator

barche commented Jan 19, 2025

I managed to get it to work by modifying the C++ code like this:

jl_value_t *ret = jl_eval_string(R"(
  summy(x,y) = x+y
  @safe_cfunction(summy, Cint, (Cint, Cint))
)");

jlcxx::SafeCFunction cFunc = jlcxx::unbox<jlcxx::SafeCFunction>(ret);
cFunc.fptr = jlcxx::unbox<void*>((jl_value_t*)cFunc.fptr); // no idea why the pointer itself is also boxed here
auto fptr = jlcxx::make_function_pointer<int(int, int)>(cFunc);

return fptr(a, b);

It seems the pointer that comes back out is still boxed. I think the reason for that is that SafeCFunction is an immutable type, which normally can't be passed around using pointers the way it is done here. I'm not sure that these hacks are reliable, so I would recommend only passing a SafeCFunction as an argument to a ccalled function (can be a function wrapped using CxxWrap).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants