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

discussion: adding additional c or c++ binding #3098

Closed
u007 opened this Issue Aug 5, 2016 · 7 comments

Comments

Projects
None yet
5 participants
@u007

u007 commented Aug 5, 2016

hi,

i saw the docs that show ways to bind functions from a c library.
can i also bind c++ library?

and how do i compile this binding?
which directory and file name and file extension that i need to put into,
and what command do i need to invoke and require the binding to be able to use the library?
and where should i place the library? will compiled binary works? or i need to get the c library source code to compile for crystal use?

thank you

@jhass jhass added the kind:question label Aug 5, 2016

@jhass

This comment has been minimized.

Member

jhass commented Aug 5, 2016

As far as am I'm aware, C++ symbol mangling is not well specified, so there's no standard we could implement that would work well across libraries compiled with different compilers. For this reason Crystal itself does have a small C wrapper around some of LLVMs C++ only interfaces, providing well defined symbol names: https://github.com/crystal-lang/crystal/blob/master/src/llvm/ext/llvm_ext.cc

The binding is regular Crystal code, you put it into a regular Crystal file and require it, like any other Crystal code. The @[Link] attribute defines flags that will be included in the final linker invocation, so you should put a shared or static library into your standard linker paths (or extend it by setting LIBRARY_PATH or specifying the -L flag either in the @[Link] attribute or the --link-flags option to the crystal build command), which provides the symbol names you specified in the binding.

Crystal does not read the libraries C code in any way currently, nor tries to compile it, it just links against it.

@asterite

This comment has been minimized.

Contributor

asterite commented Sep 1, 2016

I'm closing this. The explanation @jhass gave is correct: C++ symbol mangling is not well specified.

@asterite asterite closed this Sep 1, 2016

@ysbaddaden

This comment has been minimized.

Member

ysbaddaden commented Jan 4, 2017

Since C++ is capable to build libraries, and thus libraries can be interacted with from C++, I guessed it was possible to have some compatibility layer.

I found out, there is a compiler level compatibility, with no exact specifications, but, an incredible peraon, Agner Fog, analyzed and reversed the mangling of a bunch of compilers, and there are 2 major ones: MSVC and GNU 3 (with GNU 4 being a slight evolution). The specs can be found at the following addresses:

So, it may be possible to write a C++ bindings generator. That being said, it may be a crazy, and hard, task.

@ysbaddaden

This comment has been minimized.

Member

ysbaddaden commented Jan 4, 2017

(that could open up a huge world, though: LLVM, QT, Unity, the Unreal Engine, ...)

@Sija Sija referenced this issue Jan 19, 2017

Closed

C++ interop #3916

@sergeych

This comment has been minimized.

sergeych commented Dec 4, 2018

Let's make static stubs generated at compile time. It will not let connect methods dynamically, but 95% of code would not need it! If we require that C++ class definition will initially be include into .cr source, we can do it rather simple:

cppClass = CppStub.class({ 
  header_path: "/path/to/headers",
  library: "/where/so/or/dll/whatever",
  class_name: 'Point', constructors: [ (Int32, Int32) ], 
  method: (name: "length", args: [], return: Float64), attribute: {name: "x", return:  Float64...
  })

then the crystal compiler (of compiler plugin if any) extracts it and creates cc bridge code for it (sort of):

#include "cpp2crystal.h"
#include "path_to_lib/include/point.h"

extern "C" bridge_for_Point_contructor1;
CPPRESULT bridge_for_Point_contructor1(int i1,int i2) {
  try {
    return CPP_OK(new Point(i1, i2));
  }
  catch(std::exception& e) {
    return CPP_ERROR(e.what());
  }
  catch(...) {
    return CPP_ERROR(NULL);
  }
}

The same way it creates C-stubs for each method calls and maybe even for property acceess. LLVM could compile it in separate process while main code is being compiled, then we link it together, use existing C bridge code of crystal and get full-sized C++ integration in our executable. Why don't we? as @ysbaddaden said, the huge wold waits. It will really add a great value to crystal lang.

@ysbaddaden

This comment has been minimized.

Member

ysbaddaden commented Dec 5, 2018

@sergeych

This comment has been minimized.

sergeych commented Dec 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment