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

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

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

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

u007 opened this issue Aug 5, 2016 · 7 comments

Comments

@u007
Copy link

@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
Copy link
Member

@jhass 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
Copy link
Member

@asterite 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
Copy link
Contributor

@ysbaddaden 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
Copy link
Contributor

@ysbaddaden ysbaddaden commented Jan 4, 2017

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

@Sija Sija mentioned this issue Jan 19, 2017
@sergeych
Copy link

@sergeych 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
Copy link
Contributor

@ysbaddaden ysbaddaden commented Dec 5, 2018

@sergeych
Copy link

@sergeych sergeych commented Dec 7, 2018

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

Successfully merging a pull request may close this issue.

None yet
5 participants