You are viewing a plain text version of this content. The canonical link for it is here.
Posted to proton@qpid.apache.org by "Mary hinton (JIRA)" <ji...@apache.org> on 2012/12/23 19:16:12 UTC

[jira] [Commented] (PROTON-68) Porting Issue -- dll imports and exports on Visual Studio

    [ https://issues.apache.org/jira/browse/PROTON-68?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13539067#comment-13539067 ] 

Mary hinton commented on PROTON-68:
-----------------------------------

This Jira is one of the simpler changes to make to the proton codebase to add the Windows port. But it is also a large code change, since we need to add a define to all the functions, classes, etc. that will be exported from the proton dll  and will also need to include a dll  defines header file in all the .c  files.

Before I set up this Jira I looked at the way QPID handled it and set up something I thought was similar.

QPID uses the XXX_ EXPORTS preprocessor definitions that are set up in cmake for the various dlls.The xxx represents  the dll project name. For example, in the qpidcommon project, it uses  qpidcommon_EXPORTS as a Preprocessor Definition. I used qpid_proton_EXPORTS.

Is there a defined interface for proton or is everything in the header files considered the interface?  I didn’t know what was exported just for testing to use in python(ruby, etc.)  and what would actually be exported in code that loads the dll, I used a separate define for the python. Thinking that a lot of the functions are only going to be exposed for testing and not for general use, I made a separate qpid_proton_python_EXPORTS.

The better approach would probably be to use one preprocessor define. It’s just that all the functions can be imported, which is  the default for gcc and mingw dlls, but not Visual Studio. So I’ll change the code to only use qpid_proton_EXPORTS (or qpid-proton_EXPORTS) as the preprocessor definition  and only use one define. Using only one define should also remove the SWIGWIN problem, I ran into.

QPID also used a separate macro for classes and inlines.  For example, QPID_CLASS_EXPORT
We could do that, or just use one define whether it is a function structure, inline etc..

We will also need to include the dll defines header file, in the .c files, so that posix operating systems can ignore the definitions and windows operating system will export or import the functions, classes, etc, as the case may be.

In QPID, qpidcommon dll uses CommonImportExport.h, qpidbroker dll used BrokerImportExport.h". I used QPID_PROTON.h, but  will use whatever  the proton developers group prefers. E.g. ImportExport.h or ProtonImportExport.h .

For the export/import defines themselves, an example of QPID is:
#  define QPID_COMMON_EXTERN QPID_EXPORT
#  define QPID_COMMON_CLASS_EXTERN
I used QPID_PROTON_API because  an example from Micorosft, used ProjectNameDLL_API.

To be closer to the QPID practice, We could use:
PROTON_EXPORT

The only problem with that is sometimes the EXTERN will be set to the IMPORT.
For example from the QPID code in the “else” below:

#if defined(COMMON_EXPORT) || defined (qpidcommon_EXPORTS)
#  define QPID_COMMON_EXTERN QPID_EXPORT
#  define QPID_COMMON_CLASS_EXTERN QPID_CLASS_EXPORT
#  define QPID_COMMON_INLINE_EXTERN QPID_INLINE_EXPORT
#else
#  define QPID_COMMON_EXTERN QPID_IMPORT
#  define QPID_COMMON_CLASS_EXTERN QPID_CLASS_IMPORT
#  define QPID_COMMON_INLINE_EXTERN QPID_INLINE_IMPORT
#endif

So I think the PROTON_API is better for export or import, since it makes sense for either.

All the headers will need to be changed for a Windows port.
e.g.
PROTON_API pn_data_t *pn_data(size_t capacity);
PROTON_API void pn_data_free(pn_data_t *data);
PROTON_API int pn_data_errno(pn_data_t *data);

Here’s a good discussion about building Win dlls  from the cmake perspective:
http://www.cmake.org/Wiki/BuildingWinDLL
They used DLLDefines.h for their file, but ImportExport.h is probably better.

And another from Microsoft:
http://msdn.microsoft.com/en-us/library/ms235636.aspx

                
> Porting Issue -- dll imports and exports on Visual Studio
> ---------------------------------------------------------
>
>                 Key: PROTON-68
>                 URL: https://issues.apache.org/jira/browse/PROTON-68
>             Project: Qpid Proton
>          Issue Type: Improvement
>          Components: proton-c
>         Environment: Windows using Visual Studio 2010 
>            Reporter: Mary hinton
>              Labels: build
>
> Visual Studio dlls  use a macro to explicitly state which functions will be exported. I don’t have a list of all the functions that will be exported, so I just made the ones used by proton.c to be exportable. That left a lot that would be internal to the dll only. Then when I was working with the python, I realized that python was going to be importing a lot of functions from the dll that should never be exported unless testing, so I defined another macro for the python (ruby, etc) exported functions. Swig also had to be taken into account. 
> This is what I’m using right now and it should work on the Linux/Unix platform:
> #ifdef SWIGWIN
>        #define QPID_PROTON_API
> #else
>        #ifdef  _WINDOWS
>               #ifdef qpid_proton_EXPORTS
>                      #define QPID_PROTON_API __declspec(dllexport)
>                      #ifdef qpid_proton_python_EXPORTS
>                            #define QPID_PROTON_PY  __declspec(dllexport)
>                      #else
>                            #define QPID_PROTON_PY 
>                      #endif
>               #else
>                      #define QPID_PROTON_API __declspec(dllimport)
>                      #ifdef qpid_proton_python_IMPORTS
>                            #define QPID_PROTON_PY     __declspec(dllimport)
>                      #else
>                            #define QPID_PROTON_PY
>                      #endif
>               #endif
>        #else
>               #define QPID_PROTON_API
>        #endif
> #endif
> That means all the headers will need to be changed to include the macros.
> e.g.
> QPID_PROTON_API      pn_data_t *pn_data(size_t capacity);
> QPID_PROTON_API      void pn_data_free(pn_data_t *data);
> QPID_PROTON_PY       int pn_data_errno(pn_data_t *data);

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira