Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix compiler warnings when initializing extern variables #26

Conversation

martin-olivier
Copy link
Owner

Description

fix: gcc warnings when initializing extern variables

Changes include

  • Bugfix (non-breaking change that solves an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (change that is not backwards-compatible and/or changes current functionality)

Checklist

  • I have assigned this PR to myself
  • I have added at least 1 reviewer
  • I have tested this code
  • I have added sufficient documentation in the code

@martin-olivier martin-olivier added the bug Something isn't working label May 13, 2022
@martin-olivier martin-olivier self-assigned this May 13, 2022
@martin-olivier martin-olivier linked an issue May 13, 2022 that may be closed by this pull request
DYLIB_API double pi_value = 3.14159;
DYLIB_API void *ptr = (void *)1;
DYLIB_API double pi_value;
DYLIB_API void *ptr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you actually need the extern declaration, though?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DYLIB_API marks the function / variable as extern "C" and also as __declspec(dllexport) on windows.

i don't know if compilers can do name mangling on variables but DYLIB_API will still be necessary for variables to apply __declspec(dllexport) on windows

Copy link
Contributor

@eyalroz eyalroz May 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need it to be extern "C", mark it that.

__declspec(dllexport) is what you use in the DLL; in the code using the DLL function I think you want __declspec(dllimport) .

At any rate, it's not DYLIB_API that you want to use. Or rather - you could define two macros, DYLIB_IMPORT and DYLIB_EXPORT.

Finally - what if the function is not extern-C? What if it's an overloaded C++ function?

Copy link
Owner Author

@martin-olivier martin-olivier May 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what i have read __declspec(dllimport) seems useless when dll is loaded at runtime with LoadLibrary and GetProcAddress.

What if the function is not extern-C?

If the function is not extern "C", the compiler will do name mangling, making hard and non cross-(compiler / platform) way for the core to retreive symbols from the dynamic lib

What if it's an overloaded C++ function?

If multiple overloaded functions are marked as extern "C", the build of the dynamic library will fail because of multiple definition, since they will all have the same symbol name.

The only way i know to be able to have overloads on a dll is by passing throught an api :

// api.hpp

#include <string>

class api {
public:
    virtual ~api() = default;
    virtual void print(const std::string &req) = 0;
    virtual void print(const char *req) = 0;
}
// lib.cpp

#include "api.hpp"
#include "dylib.hpp"

class implem : public api {
public:
    void print(const std::string &req) override {
        std::cout << "std::string overload > " << req << std::endl;
    }
    void print(const char *req) override {
        std::cout << "char * overload > " << req << std::endl;
    }
}

DYLIB_API api *get_module() {
    return new implem;
}
// main.cpp

#include <memory>
#include "api.hpp"
#include "dylib.hpp"

int main() {
    dylib lib("./lib", dylib::extension);
    auto factory = lib.get_function<api *()>("get_module");
    std::unique_ptr<api> obj(factory());
    obj->print("first");
    obj->print(std::string("second"));
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the function is not extern-C?

If the function is not extern "C", the compiler will do name mangling, making hard and non cross-(compiler / platform) way for the core to retreive symbols from the dynamic lib

But the whole library is brittle and platform-specific. Are you the library only supports C functions? Then the README is misleading. A C++ library for working with shared objects should absolutely support C++ functions. I'll open a separate issue.

example/lib.cpp Show resolved Hide resolved
@martin-olivier martin-olivier changed the base branch from main to dev May 17, 2022 19:26
@martin-olivier martin-olivier deleted the 25-avoid-compiler-warnings-about-initializing-externs branch June 1, 2022 09:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants