1

I have a function declaration inside my shared library (*.dll) and the definition is inside another application, here is a minimal code. but how to tell the compiler find the symbol set_x (inside the mylib.cpp) at run time after the library loaded to the application. the extern keyword search it at link time. or is there any other way to call a method defined in the application.cpp?

// mylib.cpp compiles to mylib.dll
class MyClass{
public:
    extern void set_x(int); // need to tell the compiler to search at runtime
}

extern "C"{
EXPORT_API void lib_func(MyClass* o){
    printf("setting o's x value");
    o->set_x(42);
}
}
// application.cpp compiles to application.exe
class MyClass{
private:
    int x = 0;
public:
    extern void set_x(int _x){ x = _x; }
}

typedef void (*func_ptr)(MyClass*);
...
func_ptr lib_func = (lib_func_ptr)dlopen_and_get_func_ptr("mydll.lib", "lib_func");
MyClass cls;
lib_func(&cls);
...
thakee nathees
  • 877
  • 1
  • 9
  • 16
  • 1
    Normally, you would `link` to the binary which contained the implementation. But you can't link to an executable. That's what libraries are for. Move the implementation into `mylib.dll` or into a new library and link both targets to it. – Stewart Apr 11 '20 at 06:17
  • when an application using some functions from a library they must be defined inside the library but here the shared library need access to some function inside the application, and the shared library is like a script which could load and unload at runtime. @Stewart – thakee nathees Apr 11 '20 at 06:33

1 Answers1

1

The thing is that you're mixing C and C++ concepts. Even if the 2nd was built on top of the 1st, they have very different ways of dealing with this situation. I'm going to ficus on C++.
However, no matter which approach is to be chosen there are some things that are wrong in the code:

  • MyClass definition appears twice and differs (also - personal remark - I find names that start with "My", brain scratching)
  • The class is not exported

dll00.h:

#pragma once

#if defined(_WIN32)
#  if defined(DLL00_EXPORTS)
#    define DLL00_EXPORT_API __declspec(dllexport)
#  else
#    define DLL00_EXPORT_API __declspec(dllimport)
#  endif
#else
#  define DLL00_EXPORT_API
#endif


class DLL00_EXPORT_API BaseClass {
public:
    virtual void setX(int x) = 0;  // Pure virtual
    // Some other method declarations might go here. Their implementation should be in dll00.cpp
};


DLL00_EXPORT_API void callSetX(BaseClass *pClass, int value);

dll00.cpp:

#define DLL00_EXPORTS
#include "dll00.h"

#include <iostream>

using std::cout;


void callSetX(BaseClass *pClass, int value) {
    if (!pClass) {
        cout << "NULL pointer!\n";
        return;
    }
    cout << "Setting x\n";
    pClass->setX(value);
}

main.cpp:

#include "dll00.h"
#include <iostream>

using std::cout;


class DerivedClass : public BaseClass {
public:
    void setX(int x) override;

private:
    int x;
};


void DerivedClass::setX(int x) {
    std::cout << "setX(" << x << ")\n";
    this->x = x;
}


int main() {
    DerivedClass *pInst = new DerivedClass;
    callSetX(pInst, 255);
    return 0;
}

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q061152778]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.21
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

[prompt]> dir /b
dll00.cpp
dll00.h
main.cpp

[prompt]> cl /nologo /MD /DDLL /EHsc dll00.cpp  /link /NOLOGO /DLL /OUT:dll00.dll
dll00.cpp
   Creating library dll00.lib and object dll00.exp

[prompt]> cl /nologo /MD /EHsc main.cpp  /link /NOLOGO /OUT:main.exe dll00.lib
main.cpp
   Creating library main.lib and object main.exp

[prompt]> dir /b
dll00.cpp
dll00.dll
dll00.exp
dll00.h
dll00.lib
dll00.obj
main.cpp
main.exe
main.exp
main.lib
main.obj

[prompt]> main.exe
Setting x
setX(255)

For more details on exporting stuff from .dlls, you could check [SO]: Linker error when calling a C function from C++ code in different VS2010 project (@CristiFati's answer).

Note: On Nix, I've often seen this behavior (in C): an .so referencing symbols defined in the executable that loads it (one such example is static Python (where the core is in the executable), and the symbols are referenced by the extension modules), but on Win (at least VStudio compiler) this is not possible.

CristiFati
  • 38,250
  • 9
  • 50
  • 87