Calling C ++ Methods from C

So, some time has passed since I used direct C. And I am in a project where I am working on an API in C ++. Most of these methods are in any case equal to C, and all return values โ€‹โ€‹are C. structures. Except for one. One of the methods should return vector<string> . Now here is my question. Are C ++ methods / libraries / any called from C? I ask because I donโ€™t know if people using the API will write in C or C ++, and I feel that I should only return structures C. This will require me to return char** , right?

I hope this made sense if not for:

tl; dr version - Is it possible to call a C ++ method from C if it returns a C structure and if this is the best (only?) equivalent return value vector<string> โ†’ char** ?

Update: C ++ methods are just global methods. They do not have classes or objects oriented to objects. The only thing specific to C ++ that is different from my vector question is a few stringstreams

+7
c ++ c
source share
6 answers

No, C cannot use C ++ functions that are also not available in C. However, C code can indirectly use C ++ code. For example, you can implement the C function using C ++, and you can use opaque types in the interface so that the signature uses void* , but the implementation uses the C ++ class.

The equivalent of the <string> vector in C is probably closer to:

  typedef const char* c_string_type; typedef struct c_string_array { c_string_type* c_strings; int c_strings_count; } c_string_array_t; 

With opaque types you will have something like:

  typedef void* c_string_array_t; int c_string_array_length(c_string_array_t array); const char* c_string_array_get(c_string_array_t array, int index); 

Then you could secretly (in a C ++ implementation) pour std :: vector * into void *.

+6
source share

You can technically call anything from C if the function name is C-visible (prototypes, etc. are ignored at the ABI level). Of course, you cannot expect the correct results if C cannot generate the parameters as expected. Typically, the obvious solution is to simplify the interface to C. char ** is a great choice for the largest common denominator with vector<string> . Not only that, if you know what you intend to do with it, perhaps faster (and cleaner IMHO).

Regarding C visibility: the function name cannot be used in conjunction with any other visible C functions. If you want your C ++ function to be called from C, this might be a good prototype example:

 extern "C" char **lots_of_strings(); 

If the parameter signature is different, C ++ allows you to overload functions that are visible only with C ++, and allows them to coexist with the C version:

 vector<string> lots_of_strings(int); extern "C" char **lots_of_strings(); 

If you want to provide several ways to call it suitable for the calling language, you can try this (ignoring the late initialization flaws and the fact that bool exists in C):

 bool lots_of_strings(vector<string> &); extern "C" int lots_of_strings(char ***); Whatever lots_of_strings(SomeArrayType &); 

Remembering that in each case, C ++ will choose the definition with the best matching signature to the call site, and C will take whatever it can (which is always one function with the corresponding name).

It will be useful for you to hide C ++ - isms from C by combining #ifdef with the __cplusplus macro.

+6
source share

See this FAQ . Basically, you cannot call C ++ methods (member functions), but you can call stand-alone functions if they are declared using extern C. char ** is not the only possibility, but it is probably the easiest. You can return a dynamically allocated char * array. You will need to use the out parameter to provide the length to the caller (you can NULL terminate it, but this is probably not ideal). For example.

 char **get_string_list(size_t *len) { char **array; size_t actual_len; // ... *len = actual_len; array = (char **) malloc(sizeof(char *) * actual_len); // ... return array; } 

You must somehow free the memory. Either provide a function or a document as the caller should do this. Remember to free separate lines if they are dynamically allocated.

+5
source share

I read a few lines about this a while ago, and iirc you can use C ++ code / structures that will be compiled in C. But there is something about static initialization, if I understood correctly, you should write your main function in C ++ to ensure that this si is done, the C principal does not.

0
source share

If you intend to offer the same functionality for both C and C ++, I would try to offer two entry points so that you can adapt them to each other. Please note that although you can agree to an interface that can be used with both C and C ++, in most cases the C interface will not be ideal for use in C ++ (using char** may be a good solution for C, but at the same time, users convert this to return to C ++ types and perform a cleanup, can clutter up user code) and vice versa.

0
source share

If you have the opportunity to change the code you are calling, I suggest changing the function from returning the vector to something like:

 unsigned int MyFunction(char* buff, unsigned int numLines, unsigned int stride) 

Where numLines is the number of selected lines, and the step is the size of the lines. This way, your function does not need to allocate any memory that you need to worry about later. All of this is handled by the caller. The return value of the function is the number of rows that were used.

0
source share

All Articles