I'm developing an application which has to run on Linux and Windows.
I have an object called obj which I want to use in the code and it has different behavior on Linux and Windows. so I inherit aaa and called WindowsObj for Windows object and LinuxObj for Linux object.
My question is: How to use this object in the code? what do I have to write that it will run both for Linux and Windows?
For swiching types I use typedef like:
typedef uint32_t DWORD;
but what do I have to use for objects?
I want to write this code:
tr1::shared_ptr<WindowsObj> windowsobj (new WindowsObj(parameter));
tr1::shared_ptr<LinuxObj> linuxobj (new LinuxObj(parameter));
Any idea?
The same thing :)
class _object
{
};
class WindowsObject : public _object
{
};
class LinuxObject public _object
{
};
#if defined(WIN32)
typedef WindowsObject Object;
#else
typedef LinuxObject Object;
#endif
Object myObject;
EDIT: Naturally, the interface that WindowsObject and LinuxObject expose must be the same. In this example, _object would be an abstract base-class that defined the interface, and LinuxObject and WindowsObject would then implement this interface, hiding away the platform-specific stuff in their implementation files.
Sample
_object.h
class _object
{
public:
virtual void doSomething() = 0;
}; // eo class _object
WindowsObject.h
#include "_object.h"
class WindowsObject : public _object
{
public:
virtual void doSomething();
}; // eo class WindowsObject
WindowsObject.cpp
#if defined(WIN32)
#include <windows.h>
void WindowsObject::doSomething()
{
// do something totally reliant on windows here
}; // eo doSomething
#endif
Then you would do the same for LinuxObject.h and LinuxObject.cpp, the latter having completely different preprocessor instructions. e.g, #if defined(UNIX) or some such flavor. Note the WIN32 guards around the implementation. Then you'd have some core header file you'd use:
#if defined(WIN32)
#include "WindowsObject.h"
typedef WindowsObject Object;
#else
#include "LinuxObject.h"
typedef LinuxObject Object;
#endif
Now, in your program
Object a;
a.doSomething();
It's worth noting that, if it's just the odd line of code that differs in your complex object (like a init call at initialisation, destruction) you might be better off with a single platform-agnostic Object and put guards in the implementation. This solution makes more sense when there are huge differences.
I tend to use conditional compilation for this, e.g.
#ifdef WIN32
// windows-specific code
#else
// non-windows
#endif
I suggest to use a cross platform framework, like GTK+ or wxWidgets, so that you hadn't to reinvent the wheel...
Then, you should have the least possible platform depended code, and possibly well deep-inside your classes. There you can use #ifdef to conditionally include code for Windows or for Unix.
You may use the same header file with two different implementations in two different .cpp files; the PIMPL idiom makes this possible even if the two implementations require completely different data members. You simply compile and link one source when compiling for Windows and a different one when compiling for Linux.
One area that I've found this useful is for email interfaces. The two OS have completely different methods for sending emails.
Hi if you can use c++, use boost and size_t type its better way.
Related
So I want cross-platform compatibility for my library with MacOS and Windows. To achieve this I have almost identical classes for each platform: MyClassMacOS & MyClassWin. At compile time, I want to use only one of them and rename it so the user only sees MyClass and I am trying to do it like this:
header.h
#if __APPLE__
# include "MyClassMacOS"
namespace n {
typedef n::MyClassMacOS MyClass
}
#if __WIN__
# include "MyClassWin.h"
namespace n {
typedef n::MyClassWin MyClass
}
I have the typedefs wrapped in a namespace to preserve the namespace the original MyClass is wrapped in.
The problem is that the code-completion system is displaying both the original definition and the new typedef definition. Is there a way to hide the original definition and just show the new one? Perhaps I should look into a different way for achieving cross platform?
Things I have considered:
renaming MyClassWin and MyClassMacOS to something else... but then it will still show up in the hints and might confuse the user.
renaming MyClassWin and MyClassMacOS to __MyClassWin and __MyClassMacOS, it'll still show up in the code completion, but only if you start typing "_". However, seems like __ names are reserved for the compiler.
The simplest solution would be to switch the implementation completely, without letting the other one exist, since you can only have one per platform:
#if __APPLE__
struct MyClass {
auto function() -> int;
};
#elif __WIN__
struct MyClass {
auto function() -> int;
};
#endif
But for the sake of organizing your code, you can put them in different headers:
myclass_apple.h:
struct MyClass {
auto function() -> int;
private:
AppleSpecificStuff stuff;
};
myclass_win.h:
struct MyClass {
auto function() -> int;
private:
WinSpecificStuff stuff;
};
myclass.h:
#if __APPLE__
#include "myclass_apple.h"
#elif __WIN__
#include "myclass_win.h"
#endif
Then, you can put the different implementation in different .cpp files. In your build system, simply compile the one that is relevant to the current platform.
I need to maintain a project that supports running on Linux and Windows. Some codes using preprocessor directives like this are fine.
#ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
#include <windows.h>
#else
#include <unistd.h>
#endif
But some are the actual implementation, which I would like to prevent using preprocessor directives.
void Foo()
{
#ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
code for windows
#else
code for Linux
#endif
some common code...
#ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
code for windows again
#else
code for Linux again
#endif
}
So things get convoluted and harder to maintain. Is there any better way?
The traditional way is to "hide" all the code that is specific to any OS in wrapper functions - you can either do that in complete functions that do a higher level functionality - e.g. have a function that returns all directory entries based on a given path as input, or implement the individual base-functions, e.g. start_read_directory(path), read_dir_entry(), end_read_directory() - that's just an example functionality, the same principle(s) can be applied on almost any system specific functionality. Wrap it enough, and you wouldn't be able to tell what you are programming for.
In essence, you are doing it wrong if you have a lot of #ifdef in the code itself.
Handle the OS specifics from the build system, not the code. For instance, have two versions of Foo.cpp: one that gets compiled on Linux and another on Windows. Ideally, the header file will be common and all function signatures identical.
You can use a simplified version of the factory pattern.
Have a common interface
class MyClass
{
public:
virtual void Foo() = 0;
};
And for each platform you create a specific class
#import <windows.h>
class MyClassWindows : MyClass
{
public:
virtual void Foo() { /* Do something */ }
};
#import <linux.h>
class MyClassLinux : MyClass
{
public:
virtual void Foo() { /* Do something */ }
};
Then when you need this class, you use your factory:
class MyClassFactory
{
public:
static MyClass* create()
{
#if defined _WIN32
return new MyClassWindows();
#elif defined _LINUX
return new MyClassLinux();
#endif
}
}
There a many variants of this methods, including defining the MyClassFactory::create method in the .cpp of each platform-specific class and only compiling the .cpp for the appropriate platform. This avoids all preprocessing directives, the switching is made by choosing the correct implementation file.
A common pattern would be to provide system independent header files, and platform-specific implementation files.
Nothing platform specific in the header:
class Foo
{
...
};
In two different implementation files, foo_linux.cpp
Foo::Foo() { .. linux code }
foo_windows.cpp
Foo::Foo() { .. windows code }
and maybe platform independent implementation in foo.cpp
void Foo::plat_independent_function()
Your platform builds then link in foo.cpp and foo_platform.cpp
A possibility for the implementation of this is to use the PIMPL idiom, where your class just publishes the "interface" and declares a meaningless pointer to an implementation class (in its dark, hidden and private corner) and the build system takes care of pulling in the correct platform dependent code for the class containing the implementation of your PIMPL.
I have a C++ thread wrapper class around win32/pthreads. The problem is in my header I need alot of the biggie-include like windows.h and boost::function, for declaring my typedefs below.
Is there any way around this? I know you can forward declare classes and structs, but datatypes like the win32 HANDLE and templated functions in a namespace...?
#include "boost/function.hpp"
/* Thread wrapper class */
class IThread
{
public:
#if defined _WIN32 || _WIN64
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#undef WIN32_LEAN_AND_MEAN
typedef HANDLE ThreadHandle;
#else
#include <pthread.h>
typedef pthread_t ThreadHandle;
#endif
enum ThreadState
{
DETACHED = 0,
RUNNING,
FINISHED
};
typedef boost::function1<void, void*> Task;
virtual ~IThread() { }
IThread& operator=(IThread& other);
virtual int32_t Join() = 0;
virtual int32_t SetPriority(int32_t priority) = 0;
virtual ThreadHandle& GetNativeHandle() = 0;
virtual ThreadState GetThreadState() const = 0;
};
Thanks
I'll assume this isn't your real code because I can't see how includes could work in the middle of your class definition.
In this case you probably want to not expose the native thread identifier at all. Instead, provide abstract capabilities to act on threads in a sane manner and at no time expose the implementation details such as HANDLE. Then you can move the includes to your source file and problem averted.
Also note that doing the WIN32_LEAN_AND_MEAN + #include <Windows.h> in a header file means that someone that doesn't WANT WIN32_LEAN_AND_MEAN but includes your header before their own windows.h include will get the lean-and-mean unexpectedly.
EDIT: I think it's fine to use boost::function in the header because the include is always the same regardless of environment. As long as you always expose it as Task instead of as the function itself it can be considered part of the interface.
I've been reading questions on Stack Overflow for a few weeks now... this'll be my first question.
So recently I've looked into making C access/manipulate a C++ class. I understand that ideally one shouldn't compile components in C and C++ separately under normal circumstances, but this isn't an option at the moment.
I looked into 3 Tutorials regarding being able to port/use a C++ in C. They are:
"A Guide to C++ and C Interoperability" on DevX
"Mixing C and C++ Code in the Same Program" article on Sun's site.
"[32] How to mix C and C++" on Parashift
First, what I already know:
You must use extern "C" to avoid
C++ function name mangling.
You need callback prototypes that are C-compatible.
G++ must compile the C++ into .o files, GCC compiles the C-specific code into .o files, then link both after.
As a result, the project I have is made of 4 files:
foo.h, header that'll list all prototypes that C/C++ will see (classes invisible to C of course)
foo.cpp containing the Foo class, and a set of C-compatible callback functions to invoke the class and methods.
fooWrap.c a set of C-specific wrappers that reference the callback functions in foo.cpp.
main.c the test method.
Here's the code I typed up, then my questions:
FOO.H
// Header File foo.h
#ifndef FOO_H
#define FOO_H
//Content set inside this #ifdef will be unseen by C compilers
#ifdef __cplusplus
class Foo
{
public:
void setBar(int);
void printBar();
private:
int bar;
};
#endif
//end of C++-only visible components.
#ifdef __cplusplus
extern "C" {
#endif
//Stuff made to be seen by C compilers only. fooWrap.c has definitions.
#if defined(__STDC__) && !defined(__cplusplus)
typedef struct Foo Foo;
//C-wrappers for C++ callback functions.
Foo * c_NewFoo();
void c_SetFooBar( Foo *, int);
void c_PrintFooBar( Foo *);
#endif
//These are the functions C++ AND C can both use...
Foo * newFoo(); //allocates the memory for Foo class, pass address back.
void setFooBar( Foo * , int ); //set internal contents of Foo object.
void printFooBar ( Foo * ); //print internal contents of Foo object.
#ifdef __cplusplus
}
#endif
#endif /*FOO_H*/
TEST.C
#include "foo.h"
// test.c test file for wrappers that manipulate C++ objects.
main()
{
//looks very C++ like... this makes C-Programmers cringe doesn't it?
Foo * cfoo = c_NewFoo();
Foo * cppfoo = newFoo();
//using the C-specific wrappers.
c_SetFooBar(cfoo,31415);
c_PrintFooBar(cfoo);
//using the C/C++ callback functions to Foo objects.
setFooBar(cppfoo,9001);
printFooBar(cppfoo);
}
So I split the definitions up into the 4 files as I mentioned before... and it compiles fine. But here's what I don't quite get.
Why do the sun and parashift articles suggest to create C-Wrappers whose only code is to pass it's arguments onto C/C++ compatible functions who then call C++ specific code?
i.e.
//in Stuff.cpp
void CallCppStuff () { /* c++ stuff */ }
//in wrapStuff.c
wrapCppStuff() { CallCppStuff() }
As you can see from my test.c file... I'm able to call up either set of calls without a problem (as far as I can tell). Are the c_ wrappers needless overhead, or am I missing the whole point of them altogether? My only guess has something to do with pointer addressing schemes of C/C++... but I'm not sure.
Also, I imagine there are more issues beyond just this... but those 3 sites are all I could find specific to this problem. So if there are any other glaring oversights on my part, I'd appreciate their mentioning.
Thanks in advance for any help/advice,
CX
If you have a series of functions that are not object-orientated or in a namespace, there's no need to wrap them again. Your c_ series of functions are redundant.
Any C++ function that is extern C, has global (i.e., not namespace/static member) linkage, and only takes C-compat datatypes (normally we use opaque pointers like you have), then it doesn't need to be wrapped. That is the wrapping function. C++ uses member functions directly and doesn't need to use them, and they certainly don't need to be duped.
I have to import/translate the code from one C++ class so that I may use it in a C program.
The C program is large and has lots of dependencies on C libraries both open and closed.
The C++ Class .cpp file is 650 lines
I have no experience mixing C and C++ so even though I have looked at one guide on how to do it, I am not convinced which way to go.
I only have to use the C++ code in a few spots (fairly isolated useage
I am using gcc (gcc/g++)
It is a linux environment
So what do I have to do to import it? and will it be less time than translating?
Thanks,
Mike
Hmm, 650 lines is not too long - I'd re-write it. You will probably spend at least as much time trying to wrap it, and you may find maintaining the result difficult.
This might be useful: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
You need to create functions in C++ that are 'extern "C"', so they are callable from C.
You can get OO by making the this pointer explicit (and of type void *), with the implementation casting the pointer and forwarding to the real member function.
In your C++ code, you must use the extern "C" construct to instruct the compiler/linker to generate compatible linkage so that the C code can call your C++ code.
extern "C"
{
void my_function_that_can_be_called_from_c()
{
// ...
}
}
C code doesn't know anything about objects, so you can't easily use C++ objects from C. A common technique is to manipulate C++ objects inside the "externed" function.
Say you have the following C++ class:
#if __cplusplus // only C++ programs see this part of foo.h
class foo {
public:
// a couple constructors
foo();
foo( int);
// and a couple methods
bool dosomething();
bool doSomethingElse( std::string const&);
private:
// a bunch of private stuff which is immaterial to the C interface
}
#endif
What you can do is have a set of C-callable functions that wrap the C++ interface:
// both C and C++ programs can see this part of foo.h
#if __cplusplus // but C++ programs need to know that no name mangling should occur
extern "C" {
#endif
struct CFoo_struct;
typedef struct CFoo_struct foo_t; // used as a handle to a foo class pointer
// constructors
foo_t* CreateFoo( void);
foo_t* CreateFoo_int( int);
int CFooDoSomething( foo_t*);
int CFooDoSomethingElse( foo_t*, char const*);
#if __cplusplus
} // end the extern "C" block
#endif
Then the implementation in foo.cpp might look something like:
// in foo.cpp
extern "C" {
struct CFoo_struct {
};
// constructors
foo_t* CreateFoo( void)
{
foo* pFoo = new Foo;
// a bit of ugliness - the need for this cast could be
// avoided with some overhead by having the foo_t
// struct contain a foo* pointer, and putting a foo_t
// structure inside the foo class initialized with
// the this pointer.
return reinterpret_cast<foo_t*>( pFoo);
}
// something similar for CreateFoo_int()...
// method wrappers
int CFooDoSomethingElse( foo_t* pHandle, char const* s)
{
foo* pFoo = reinterpret_cast<foo*>( pHandle);
std::string str( s);
return pFoo->doSomethingElse( str);
}
// something similar for CFooDoSomething()
} // end extern "C" block
If you want to turn the C++ class into a Linux shared library accessible to your C programs, this answer to a previous question shows you how with a small example class.
There's various things you can do.
You can rewrite it in C. Without actually seeing the code, I don't know how much trouble that would be. Much C++ code is simply C with a few addons, and some makes heavy use of templates and overloaded functions and such.
If you're not doing this, you need to make it communicate well with C. This means providing an interface for C, and surrounding it with extern "C"{ ... } so the C++ compiler will know to make the interface C-compatible. Again, without knowing something of the C++ code, I can't tell how much work this would be. You'll need the wrapper for either of the following solutions.
You can make this a C++ project, surround every C file with extern"C" { ... }, and just link it in. If you have any C++ files, the whole compilation has to be C++.
You can make a separate library to be linked in.
What you can't do is compile C and C++ together with a C main() function, or with a C compiler. C++ is more demanding, and requires more from the main() function.
You could always try recompiling the C files you're using as C++, and wrapping the .h files for the libraries in extern "C" { ... }. Well-written C90 isn't that far from being legal C++ (although the C99 standard moved away from that some), and the compiler will flag any conversion problems you find.
Which of these is the best idea for you depends on questions like:
How easy is the C++ code to convert?
How easy is it to write a C wrapper for the C++ functionality you want?
How many changes are you willing to make to the C code?
How familiar are you with making a Linux library?