From: Branimir Maksimovic on 15 Feb 2010 05:47 Paul Bibbings wrote: > Let us say that we have a shared library, implemented in MSVC, that > exposes the following interface (pseudocode): > > // shared_lib_export.h > extern "C" { > __declspec(dllexport) std::ostream* __cdecl > GetNewStream(); // dynamically allocated > __declspec(dllexport) void __cdecl > PrintToStream(std::ostream*, const char *); > __declspec(dllexport) void __cdecl > FreeStream(std::ostream*); // deallocated > } > > Then, in an application built using another implementation, say GNU gcc, > suppose I want to do something like: > > #include <ostream> > #include "shared_lib_import.h" > > int main() > { > std::ostream* os = GetNewStream(); > PrintToStream(os, "Is this valid/safe/insane?\n"); > FreeStream(os); > > return 0; > } > I don;t think this can work. std::ostream from gcc, and std::ostream from vc are two different classes and possibly have completely different layout. You have to use COM , which is well defined (vtable layout and data parameters). Greets -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: George Neuner on 16 Feb 2010 11:01 On Tue, 16 Feb 2010 13:19:19 CST, "Martin B." <0xCDCDCDCD(a)gmx.at> wrote: > >void* and RTTI don't mix. >What might make sense is have a library header that declares a >struct ostream_handle; >and then the library only exposes pointers to this undefined type. > Because this thread involves MSVC I was actually thinking about using MFC RUNTIME_CLASS information rather than standard C++ RTTI. RUNTIME_CLASS works with void* and I have used it in situations similar to the one in this thread. You'd have to wrap standard classes to use it, but the mechanism is already there and reasonably simple to use. George -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: George Neuner on 15 Feb 2010 13:09 On Mon, 15 Feb 2010 16:42:54 CST, Maxim Yegorushkin <maxim.yegorushkin(a)gmail.com> wrote: >On 15/02/10 04:55, Paul Bibbings wrote: >> Specifically, I'm thinking here about passing pointers to standard >> library objects across implementation boundaries (and, indeed, across >> DLL boundaries). >> >> Let us say that we have a shared library, implemented in MSVC, that >> exposes the following interface (pseudocode): >> >> // shared_lib_export.h >> extern "C" { >> __declspec(dllexport) std::ostream* __cdecl >> GetNewStream(); // dynamically allocated >> __declspec(dllexport) void __cdecl >> PrintToStream(std::ostream*, const char *); >> __declspec(dllexport) void __cdecl >> FreeStream(std::ostream*); // deallocated >> } >> >> Then, in an application built using another implementation, say GNU gcc, >> suppose I want to do something like: >> >> #include<ostream> >> #include "shared_lib_import.h" >> >> int main() >> { >> std::ostream* os = GetNewStream(); >> PrintToStream(os, "Is this valid/safe/insane?\n"); >> FreeStream(os); >> >> return 0; >> } >> >> What can we say about the validity of obtaining, storing and passing >> back for use a pointer in this way? > >It won't work because MSVC and gcc have different standard libraries. >MSVC std::ostream has one declaration, gcc std::ostream has another and >they are not compatible. > >It will work with the same C++ compiler though. It _might_ work in the example because the GCC code is seeing just a pointer - not an object - and the object is being manipulated only by library code. You are correct, though, that it will fail if the pointer is used directly to access the standard object. It would be safer for the library to return a void* that the application can use only as an identifier ... but then that requires RTTI to ensure safety in the library and that may cause problems too. >> In short, can such a use ever be viable, and if so, under what >> circumstances? > >Not in C++. You would need to wrap your API in C to make it truly portable. Yes. Both MSVC and GCC can export classes from DLLs, but their different name-mangling schemes prevents cross platform use, and even if you solve that I don't know if their object representations and dispatch methods are compatible. George -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: George Neuner on 15 Feb 2010 13:09 On Sun, 14 Feb 2010 22:55:16 CST, Paul Bibbings <paul.bibbings(a)gmail.com> wrote: >Specifically, I'm thinking here about passing pointers to standard >library objects across implementation boundaries (and, indeed, across >DLL boundaries). > >Let us say that we have a shared library, implemented in MSVC, that >exposes the following interface (pseudocode): > > // shared_lib_export.h > extern "C" { > __declspec(dllexport) std::ostream* __cdecl > GetNewStream(); // dynamically allocated > __declspec(dllexport) void __cdecl > PrintToStream(std::ostream*, const char *); > __declspec(dllexport) void __cdecl > FreeStream(std::ostream*); // deallocated > } > >Then, in an application built using another implementation, say GNU gcc, >suppose I want to do something like: > > #include <ostream> > #include "shared_lib_import.h" > > int main() > { > std::ostream* os = GetNewStream(); > PrintToStream(os, "Is this valid/safe/insane?\n"); > FreeStream(os); > > return 0; > } > >What can we say about the validity of obtaining, storing and passing >back for use a pointer in this way? Can this ever be well-defined, and >what are the minimal guarantees that we must require for it to be so >(not to mention passing across the C-style string)? > >For instance, I'm guessing that the size of a pointer in both >implementations would need to be the same. Also, we have to allow the >shared library code to manage the destruction of the object pointed to, >ensuring its valid lifetime by a properly-balanced use of GetNewStream() >and FreeStream(...). More importantly, we would have to forget about >any attempts to use the object in our calling code, in the sense of >dereferencing the pointer. > >In short, can such a use ever be viable, and if so, under what >circumstances? Does the standard have anything to say to help me here? > >Regards > >Paul Bibbings The standard says nothing whatsoever about sharable libraries. The best that can be said is "it might work". It depends on the size of pointers, the type of MS DLL (regular or MFC extension), and on whether the particular versions of MSVC and GCC have compatible object structures and dispatch methods (AFAIK, all Windows compilers use SEH for exception handling). MS regular DLLs present a "C" interface, regardless of the language used to write them. COM/ATL DLLs are a version of regular DLLs. Regular DLLs have a private heap from which they normally make all allocations. There is a way to change the DLL's default heap (which is used by MFC extension DLLs to allocate from the application heap) but offhand I don't recall how to do it. I haven't looked into this for quite a while, but it used to be (circa C++ v5-v7) that trying to directly access DLL private heap objects from the application caused a protection fault. Extension DLLs have a nice C++ friendly interface, but they are a whole different matter and I doubt that GCC can cope with them. I don't know of anyone that has ever tried. As far as your example goes, exposing a functional API and using the object pointer/reference simply as an identifier is the safest way to deal with DLL objects. I just don't know whether it will work across platforms. George -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 16 Feb 2010 02:19 George Neuner wrote: > On Mon, 15 Feb 2010 16:42:54 CST, Maxim Yegorushkin > <maxim.yegorushkin(a)gmail.com> wrote: > >> On 15/02/10 04:55, Paul Bibbings wrote: >>> Specifically, I'm thinking here about passing pointers to standard >>> library objects across implementation boundaries (and, indeed, across >>> DLL boundaries). >>> >>> (....) >>> >>> What can we say about the validity of obtaining, storing and passing >>> back for use a pointer in this way? >> It won't work because MSVC and gcc have different standard libraries. >> MSVC std::ostream has one declaration, gcc std::ostream has another and >> they are not compatible. >> >> It will work with the same C++ compiler though. > > It _might_ work in the example because the GCC code is seeing just a > pointer - not an object - and the object is being manipulated only by > library code. > > You are correct, though, that it will fail if the pointer is used > directly to access the standard object. It would be safer for the > library to return a void* that the application can use only as an > identifier ... but then that requires RTTI to ensure safety in the > library and that may cause problems too. > void* and RTTI don't mix. What might make sense is have a library header that declares a struct ostream_handle; and then the library only exposes pointers to this undefined type. br, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: global variables - an alternate approach Next: File Handling |