Calling C++ from "C" (-friendly) code - am I doing it right ?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Calling C++ from "C" (-friendly) code - am I doing it right ?
I know it's a FAQ, and I read info from the WEB as well as related portions of C++ standard.
In this case I insist on compiling the final "C" part by "C" (and not C++) compiler - this is because I am trying to understand in detail how I can create bindings of something originally written in C++ for something which is written in "C" and has a well defined interface for foreign functions written in "C", but not in C++.
The code I am presenting works fine for me; I want to know whether it works correctly by construction (of course, this is my goal) or by chance.
sergei@amdam2:~/junk/c++_work/calling_c++_from_c> ./main
Point2D() called
get_y() called
get_x() called
(can be random junk) Point2D_get_x(p1) : 0 Point2D_get_y(p1) : 0
Point2D(1.23, 4.56) called
get_x() called
Point2D_get_x(p2): 1.23
Point2D_copy_constructor(void * self, void * other) called
Point2D(const Point2D &other) called
just after assigning to 't'
returning from Point2D_copy_constructor(void * self, void * const other)
~Point2D() called
get_y() called
get_x() called
Point2D_get_x(p1) : 1.23 Point2D_get_y(p1) : 4.56
~Point2D() called
~Point2D() called
sergei@amdam2:~/junk/c++_work/calling_c++_from_c>
.
So, if something is wrong with this, please tell me.
Thanks in advance,
Sergei.
P.S. Probably a better jobs with const-ness can be done - I don't yet know how, and likely it's not critical for the final goal of creating bindings.
I want to know whether it works correctly by construction (of course, this is my goal) or by chance.
I didn't spot anything that looked to me like it worked by "chance" (meaning worked by non guaranteed implementation details of your current tool set). But your code is ugly enough I can't be sure.
What are you trying to accomplish with the defines INLINE_CXX and INLINE_C ? Those don't seem to make sense, especially the latter, which doesn't look like it is or ever should be inline.
Quote:
'Point2D_C_interface.c' file - this is the implementation of the above "C" functions:
I'm bothered by that C++ source file having the extension .c and also by your terminology. The definitions for extern "C" declarations are C++ functions with C interfaces.
I also strongly prefer reinterpret_cast for converting C++ class pointers to/from C void*
In this usage, it means exactly the same to the compiler as static_cast but reinterpret_cast is correctly descriptive of the actual operation and thus more meaningful to any human reading the code.
I also think it is better to define EXTERN_C inside the interface.h using a conditional that directly checks the language (C vs. C++) that the compiler is compiling at the moment. Making the .c or .cpp file that includes the interface.h file responsible for that step is a much less maintainable design. At the moment I forget the format of the #if that tests whether the compiler is currently compiling C++, but I think that should be easy to look up.
I also think it is better to define EXTERN_C inside the interface.h using a conditional that directly checks the language (C vs. C++) that the compiler is compiling at the moment. Making the .c or .cpp file that includes the interface.h file responsible for that step is a much less maintainable design. At the moment I forget the format of the #if that tests whether the compiler is currently compiling C++, but I think that should be easy to look up.
Guys, thanks for the feedback. Actually, I do not like my own mapping of copy-constructor, and I'm going change it and to add some more stuff.
Meanwhile I'd like to better understand why 'reinterpret_cast' is more appropriate than 'static_cast'. Both are described on pages 74 .. 76 of 'C++ Standard - ANSI ISO IEC 14882 2003.pdf': http://openassist.googlecode.com/fil...2%25202003.pdf
.
I chose 'static_cast' because it has (as I understand it) less functionality, i.e., if I haven't missed something, it does not perform pointer <-> conversions. I.e. my general approach was to choose something suitable with the least possible amount of degrees of freedom.
reinterpret_cast is the most dangerous cast, and should be used very sparingly. It turns one type directly into another - such as casting the value from one pointer to another, or storing a pointer in an int, or all sorts of other nasty things. Largely, the only guarantee you get with reinterpret_cast is that if you cast the result back to the original type, you will get the same value. Other than that, you're on your own. reinterpret_cast cannot do all sorts of conversions; in fact it is relatively limited. It should almost never be used (even interfacing with C code using void* can be done with static_cast).
- guys, I really want to hear why reinterpret_cast is better. You, of course, may say the above quote is just another personal opinion, but I'd like to hear real arguments in favor/against.
I have no comments on whether to use reinterpret_cast is better/worse than static_cast. I have used the former countless times, and never encountered a "nasty" or "dangerous" experience. It is my understanding that the static_cast is the equivalent of the C-style cast.
IMHO, if you are working on a complex project, determining whether to use reinterpret_cast vs. static_cast should be the least of your worries.
- guys, I really want to hear why reinterpret_cast is better. You, of course, may say the above quote is just another personal opinion, but I'd like to hear real arguments in favor/against.
The above quote is just a personal opinion. My own opinion is also just a personal opinion.
In practice a static_cast to or from a void* does exactly the same thing as a reinterpret_cast to or from a void*.
Deep aside comment: If I understand the standard correctly, the above is true only in practice, not in theory. Those two cast methods are defined by the standard to each do the same thing (restore the original pointer) if the same one (static vs. reinterpret) is used both to void* and from void*. But the standard does not seem to say you could safely use one to go to void* and the other to go back. In practice you can.
My opinion on which is better is based on what they actually do:
When casting between pointers other than void*, a static_cast checks significant aspects of the possible correctness of the cast and adjusts the pointer correctly for the difference between base and derived class. reinterpret_cast does none of that extra work for you. It just reinterprets the pointer as the requested kind of pointer.
When casting to/from void* both static_cast and reinterpret_cast act exactly the same way only reinterpret_cast acts for non void pointers. They both do no type checking and just reinterpret the pointer. My opinion is that it is better to make that fact more obvious to any human reading your code.
In this case I insist on compiling the final "C" part by "C" (and not C++) compiler - this is because I am trying to understand in detail how I can create bindings of something originally written in C++ for something which is written in "C" and has a well defined interface for foreign functions written in "C", but not in C++.
In general, you'll need to link the C++ portion with g++ because it will sometimes create link-time dependencies with hidden object files or static libraries, not just libstdc++. If you want it to be truly C compatible you'll have to create a shared library to pre-link all the g++ dependencies, which isn't a big deal, and it certainly isn't a big hassle.
Quote:
Originally Posted by Sergei Steshenko
- guys, I really want to hear why reinterpret_cast is better. You, of course, may say the above quote is just another personal opinion, but I'd like to hear real arguments in favor/against.
As far as I know, reinterpret_cast does absolutely nothing but give you a waiver to use a pointer however you want to, i.e. a traditional C-cast. This usually isn't a problem if you're casting to the first base class, provided it's not virtual, or if you're casting back to the same class that a void pointer was cast from. In contrast, static_cast is often not necessary unless you're casting to a derived class or to avoid ambiguity with operator overloads; implicit casting takes care of almost everything.
You actually don't need a cast if you declare struct Point2D; in your C-header within extern "C" (you don't actually define the structure in C, though.) In fact, that would be the appropriate way to handle this situation rather than void*.
Kevin Barry
...
You actually don't need a cast if you declare struct Point2D; in your C-header within extern "C" (you don't actually define the structure in C, though.) In fact, that would be the appropriate way to handle this situation rather than void*.
Kevin Barry
Thanks for the tip. My solution at the moment is this:
. The point also is that I do need 'void *' in some cases in "C" - when I preallocate one way or another memory for the object. The preallocated object isn't of type Point2D :
You're leaking memory here, and invoking an assignment operator on something that hasn't been constructed is undefined. You need new (obj) Point2D; (as the entire function,) provided obj points to available memory of the correct size.
Kevin Barry
PS Similarly, in your new code line 24 has undefined behavior, although it probably still works in this situation.
...
PS Similarly, in your new code line 24 has undefined behavior, although it probably still works in this situation.
Do you mean this:
Code:
18 INLINE_C void Point2D_cast_to_this(ObjType obj)
19 {
20 Point2D t(0.0, 0.0); // any constructor call is good here - just to ensure basic initialization
21 // in order to be able to call methods later.
22 // care should be taken to make sure automatically called destructor of 't'
23 // doesn't cause problems.
24 *obj = t;
25 }
portion and its line #24 ?
What I mean is to copy everything relevant from 't' onto '*obj'. Actually, I can probably better do it using 'memcpy'.
What I mean is to copy everything relevant from 't' onto '*obj'. Actually, I can probably better do it using 'memcpy'.
Using memcpy would also work, but technically be undefined behavior. It is not any better than misusing the assignment operator.
You should try to understand the "placement new" feature of C++ (ta0kira included an example of the syntax in his last post). That feature is the technically correct way to do both of your Point2D_cast methods that are now technically incorrect.
This "placement new" is a bit confusing because it doesn't allocate any new space. In this default form of placement new, it is really just a call to the constructor on existing space (previously allocated some other way).
C++ does not allow you to directly call a constructor. So in those cases where what you want is a direct call to a constructor, you use placement new.
Placement new can also be used when you want more interesting overrides of the allocation portion of an ordinary new.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.