Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing Interfaces in c++

Tags:

c++

interface

I am developing an interface that can be used as dynamic loading.Also it should be compiler independent.So i wanted to export Interfaces. I am facing now the following problems..

Problem 1: The interface functions are taking some custom data types (basically classes or structures) as In\Out parameters.I want to initialise members of these classes with default values using constructors.If i do this it is not possible to load my library dynamically and it becomes compiler dependent. How to solve this.

Problem 2: Some interfaces returns lists(or maps) of element to client.I am using std containers for this purpose.But this also once again compiler dependent(and compiler version also some times).

Thanks.

like image 794
venkatmakam Avatar asked Nov 22 '25 05:11

venkatmakam


2 Answers

Code compiled differently can only work together if it adopts the same Application Binary Interface (ABI) for the set of types used for parameters and return value. ABI's are significant at a much deeper level - name mangling, virtual dispatch tables etc., but my point's that if there's one your compilers support allowing calling of functions with simple types, you can at least think about hacking together some support for more complex types like compiler-specific implementations of Standard containers and user-defined types.

You'll have to research what ABI support your compilers provide, and infer what you can about what they'll continue to provide.

If you want to support other types beyond what the relevant ABI standardises, options include:

  • use simpler types to expose internals of more complex types

    • pass [const] char* and size_t extracted by my_std_string.data() or &my_std_string[0] and my_std_string.size(), similarly for std::vector

    • serialise the data and deserialise it using the data structures of the receiver (can be slow)

  • provide a set of function pointers to simple accessor/mutator functions implemented by the object that created the data type

    • e.g. the way the classic C qsort function accepts a pointer to an element comparison function
like image 133
Tony Delroy Avatar answered Nov 24 '25 21:11

Tony Delroy


As I usually have a multithreading focus, I'm mostly going to bark about your second problem.

You already realized that passing elements of a container over an API seems to be compiler dependent. It's actually worse: it's header file & C++-library dependent, so at least for Linux you're already stuck with two different sets: libstc++ (originating from gcc) and libcxx (originating from clang). Because part of the containers is header files and part is library code, getting things ABI-independent is close to impossible.

My bigger worry is that you actually thought of passing container elements around. This is a huge threadsafety issue: the STL containers are not threadsafe - by design.

By passing references over the interface, you are passing "pointers to encapsulated knowledge" around - the users of your API could make assumptions of your internal structures and start modifying the data pointed to. That is usually already really bad in a singlethreaded environment, but gets worse in a multithreaded environment.

Secondly, pointers you provided could get stale, not good either.

Make sure to return copies of your inner knowledge to prevent user modification of your structures.

Passing things const is not enough: const can be cast away and you still expose your innards.

So my suggestion: hide the data types, only pass simple types and/or structs that you fully control (i.e. are not dependent on STL or boost).

like image 26
Klaas van Gend Avatar answered Nov 24 '25 20:11

Klaas van Gend