0

I have some code written in C, and there is one section that refuses to cooperate when using Visual Studio 2015 Community (clang has no problems). I have a simple struct:

/** Options for enumerating over all documents. */
typedef struct {
    unsigned          skip;     /**< The number of initial results to skip. */
    C4EnumeratorFlags flags;    /**< Option flags */
} C4EnumeratorOptions;

enum {
    kC4Descending           = 0x01, /**< If true, iteration goes by descending document IDs. */
    kC4InclusiveStart       = 0x02, /**< If false, iteration starts just _after_ startDocID. */
    kC4InclusiveEnd         = 0x04, /**< If false, iteration stops just _before_ endDocID. */
    kC4IncludeDeleted       = 0x08, /**< If true, include deleted documents. */
    kC4IncludeNonConflicted = 0x10, /**< If false, include _only_ documents in conflict. */
    kC4IncludeBodies        = 0x20  /**< If false, document bodies will not be preloaded, just
                               metadata (docID, revID, sequence, flags.) This is faster if you
                               don't need to access the revision tree or revision bodies. You
                               can still access all the data of the document, but it will
                               trigger loading the document body from the database. */
};
typedef uint16_t C4EnumeratorFlags;

And I also have a constant "default" value for it:

// In header
extern const C4EnumeratorOptions kC4DefaultEnumeratorOptions;

// In implementation
const C4EnumeratorOptions kC4DefaultEnumeratorOptions = {
    0, // skip
    kC4InclusiveStart | kC4InclusiveEnd | kC4IncludeNonConflicted | kC4IncludeBodies
};

However, when debugging I noticed that the initialization is not doing anything when I try to use the default value:

// options winds up with a "skip" value of something like 117939945
// and a flags value of 59648
C4EnumeratorOptions options = kC4DefaultEnumeratorOptions;

The section defining is in a DLL, and the second using is in an exe. Again, this only happens on Windows. Furthermore, the value in "options" is garbage but for some reason it's not even the same garbage that is stored in kC4DefaultEnumeratorOptions. I know MSVC is notorious for snubbing C, but this kind of initialization is so old that even MSVC should get it right, shouldn't it? So it must be something I am doing but I can't figure out what.

EDIT The symbol is being exported via a export definitions file. I checked with dumpbin, and found the symbol in the exported symbols list

41 46 00A6EA8 kC4DefaultEnumeratorOptions = kC4DefaultEnumeratorOptions

Also as one more bit of info, the calling code is C++ and the DLL code is C, which I suspect may be playing a part in this madness.

borrrden
  • 33,256
  • 8
  • 74
  • 109
  • 1
    How do you know it is "not doing anything" ? – M.M Nov 04 '15 at 23:34
  • also it looks like you didn't export the symbol. [see here](http://stackoverflow.com/a/19374253/1505939) – M.M Nov 04 '15 at 23:37
  • @M.M. Well perhaps it is doing something but to me the value looks uninitialized since it is totally random. I'll check to make sure the symbol is in the export list though (.def file) – borrrden Nov 04 '15 at 23:59

1 Answers1

0

The comments from @M.M helped put me in the right direction. He asked if the symbol was exported. Technically, yes, it was exported since it was in the export list but apparently I also need to export the definition. So instead of including the global symbol in the .def file, I need to manually mark it with __declspec(dllexport) or __declspec(dllimport) in two places so in the end it looks like this:

#ifdef _MSC_VER
#ifdef CBFOREST_EXPORTS
#define CBFOREST_API __declspec(dllexport)
#else
#define CBFOREST_API __declspec(dllimport)
#endif
#endif

// ...

// Header
CBFOREST_API extern const C4EnumeratorOptions kC4DefaultEnumeratorOptions;

// Implementation
CBFOREST_API const C4EnumeratorOptions kC4DefaultEnumeratorOptions = {
    0, // skip
    kC4InclusiveStart | kC4InclusiveEnd | kC4IncludeNonConflicted | kC4IncludeBodies
};
borrrden
  • 33,256
  • 8
  • 74
  • 109