Ticket #757 (new enhancement)

Opened 3 years ago

Last modified 17 months ago

Building shared libraries to simplify C++ wrappers

Reported by: jodonoghue Owned by:
Priority: normal Milestone:
Component: Cabal library Version: 1.8.0.6
Severity: minor Keywords: C++, library
Cc: Difficulty: project(> week)
GHC Version: Platform:

Description

While Haskell cannot directly link with C++ code via the FFI, it is straightforward and pretty common practice to write wrapper functions which are callable using C conventions. These can be used from the FFI.

As an example, consider the method functions setFoo and getFoo in the class Bar. Ignoring const correctness and general good design, this might look something like:

class Bar {
  private: 
    String& val;
  public:
    Bar() { val = ""; }
    String& getFoo() { return val; }
    void setFoo(const String& v) { val = v; }
}

C language wrappers would be something like:

void* "C" Bar_constructor() { return (void*) new Bar; }
char* "C" Bar_getFoo(void* ths) { 
  return (char *) ((Bar*) ths)->getFoo();
}
void "C" Bar_setFoo(void* ths, char* val) {
  ((Bar*) ths)->setFoo(String(val));
}

Cabal is quite capable of compiling this today, but a problem can arise when the code is linked.

The issue is that most C++ code needs to be linked with the C++ standard library, libstdc++ (in the example above, it is needed for the String type). On Windows, the MinGW compiler provided in Haskell Platform provides only a static version of libstdc++.

When compiling with GHC, this is not an issue, since static linking to libstdc++ works just fine. However, when loading the library into GHCi, loading fails because no shared version of libstdc++ exists, and fix-up fails when attempting to load libstdc++.

The proposed solution is to extend Cabal so that C or C++ code listed in the c-sources stanza can (optionally) be built as a shared library. The shared library can safely be linked with a static libstdc++, which removes the need to export this dependency to Haskell (GHC/GHCi need only link to the shared lib).

Concretely, this could be implemented as follows:

Add a new section ForeignLibrary

This would need to contain the following stanzas:

foreign-lib-name: <name> This is the basename of the library (i.e. without the 'lib' prefix on Unix, and without any extension (.a, .so, .dll) - as this basename is cross-platform compatible.

foreign-lib-type: shared | static Indicate whether the library should be compiled as a shared library (.dll, .so, .dylib etc) or as a static library (.a, .lib).

foreign-lib-extralibs: <list of libs> A list of libraries with which the foreign library must be linked. In the case where the library is being built as shared, these will not be added to the list of libraries in the module extra-libraries stanza. Where the foreign library is built as static these libraries need to be added to extra-libraries

foreign-lib-libdirs: <list of directory paths> Each path gets added to a -L<path> when compiling C/C++ code.

foreign-lib-includes: <list of directory paths> Each path gets added to a -I<path> when compiling C/C++ code.

foreign-lib-generate-def: True | False For Windows only, if the library is being built as a shared library, generate the corresponding .def file detailing the exported functions.

cc-options, ld-options and frameworks should function in the same way as they do in Cabal today.

I believe that this set of changes would be sufficient to allow wrapping of many C++ libraries without the need for significant customization of the Cabal Simple profile.

I believe that it might also simplify porting of foreign libraries which were originally designed for Unix systems to run on Windows, since there would be a standard way to build C/C++ code for inclusion with Haskell modules.

Change History

Changed 3 years ago by duncan

See also ticket #148 about a new section type for building foreign libs. Ticket #704 is also closely related.

Changed 2 years ago by guest

It looks everything in the above description applies equally well if we replace C++ with Objective-C. Having support for Objective-C libraries inside a cabal package would greatly enhance our ability to take advantage of native APIs on OSX.

In fact, the description in the ticket probably applies equally well to any of the languages that gcc can link to C. Perhaps it would work for Fortran and Ada as well for example?

I think this feature should be a high priority.

Changed 2 years ago by guest

I'm unable to add myself to the CC, but my email address is dagitj@… and I'd like to get updates if possible.

Changed 17 months ago by elga

Note: See TracTickets for help on using tickets.