使用共享对象中的应用程序对象

发布于 2024-11-30 23:53:57 字数 1639 浏览 0 评论 0原文

我现在有点困惑。昨天,即使我将 -rdynamic 与 g++ 一起使用,我也有未定义的符号。但现在我没有任何错误,这更令人不安。

为了解释一下我的情况,我想做一些类似共享对象的插件。我还没有决定哪一个是最好的方法。

A)我的共享对象都有一个名为 register 的函数,它将使用参数来调用。这将是一个插件管理器。

B) 我的共享对象将定义一个类,并在加载时创建该类的实例。在该类的构造函数中,它将尝试从应用程序获取静态单例并自动注册自己。

据我所知,到目前为止我的第一次尝试并不是那么好。

main.cpp

#include "main.hpp"
#include <iostream>
#include <cstdio>
#include <dlfcn.h>

int S::shared = 0;

int main(int argc, char** argv){
    std::cout << "In main -> " << S::shared << "\n";

    void* triangle = dlopen("./libtwo.so", RTLD_LAZY);

    if(triangle == NULL){
        std::cout << "Error while loading so file\n" << dlerror() << "\n";
    }

    std::cout << "In main -> " << S::shared << "\n" << triangle;
    return 0;
}

main.hpp

class S {
    public:
    static int shared;

    S(){
        S::shared = 0;
    };
};

Two.cpp

#include "main.hpp"
#include <iostream>

class MyObject {
    public:
    MyObject(){
        std::cout << "In two -> " << S::shared  << "\n";
    }
};

MyObject t();

在该示例中,S::shared 是我要共享的静态对象。对于这个简单的测试,我只使用 int,但将来它将是类的实例。

我对案例 A) 的唯一尝试是一个段错误......我真的不知道我错过了什么。

//到目前为止的结果(今天)

piplup@vika:~/dev/WebDesign/Scproci$ scons -Q
g++ -o two.os -c -fPIC two.cpp
g++ -o libtwo.so -shared two.os
g++ -o main.o -c -fPIC main.cpp
g++ -o main -Wl,--export-dynamic main.o -ldl
piplup@vika:~/dev/WebDesign/Scproci$ ./main
In main -> 0
In main -> 0

I'm a little confused right now. Yesterday I had undefined symbols even if I used -rdynamic with g++. But now I don't have any error and that is even more disturbing.

To explain a bit my case, I want to do some sort of plugin like shared object. I haven't decided yet which is the best way to do.

A) My shared objects all have a function called register which will be called with a parameter. This will be a plugin manager.

B) My shared object will define a class and will create and instance of that class at load time. In the constructor of that class it will try to get a static singleton from the app and auto register himself.

As far as I can tell my first attempts weren't so great so far.

main.cpp

#include "main.hpp"
#include <iostream>
#include <cstdio>
#include <dlfcn.h>

int S::shared = 0;

int main(int argc, char** argv){
    std::cout << "In main -> " << S::shared << "\n";

    void* triangle = dlopen("./libtwo.so", RTLD_LAZY);

    if(triangle == NULL){
        std::cout << "Error while loading so file\n" << dlerror() << "\n";
    }

    std::cout << "In main -> " << S::shared << "\n" << triangle;
    return 0;
}

main.hpp

class S {
    public:
    static int shared;

    S(){
        S::shared = 0;
    };
};

two.cpp

#include "main.hpp"
#include <iostream>

class MyObject {
    public:
    MyObject(){
        std::cout << "In two -> " << S::shared  << "\n";
    }
};

MyObject t();

In that sample S::shared is the static object I would share. For this simple test I only use a int but in the futur it would be an instance of a class.

My only attempt at case A) was a segfault... I really don't know what I missed.

//Results so far (today)

piplup@vika:~/dev/WebDesign/Scproci$ scons -Q
g++ -o two.os -c -fPIC two.cpp
g++ -o libtwo.so -shared two.os
g++ -o main.o -c -fPIC main.cpp
g++ -o main -Wl,--export-dynamic main.o -ldl
piplup@vika:~/dev/WebDesign/Scproci$ ./main
In main -> 0
In main -> 0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

碍人泪离人颜 2024-12-07 23:53:57
#include "main.hpp" 
#include <iostream>  

class MyObject {     
    public:     
        MyObject(){         
            std::cout << "In two -> " << S::shared  << "\n";     
        } 
};  

MyObject* t;

__attribute__((constructor))
void init_two()
{
    t = new MyObject();
}

__attribute__((destructor))
void uninit_two()
{
    delete t;
}

这应该会产生预期的结果。使用指针是因为在共享对象中显式处理它们更容易,因为常规初始化不会自动发生。如果您不想使用指针,请为您的类提供显式初始化并在共享库初始化函数中调用它。

* 编辑*

我做了一些额外的实验,看起来如果您使用默认构造函数,则隐式使用它并且它将被调用,如果您使用非默认构造函数则照常调用。

所以你可以将你的:

MyObject t();

调用更改为:

MyObject t;

并且它可以在没有定义显式初始化函数的情况下工作。

class MyObject {
public:
   MyObject() { /* as before */ };
   MyObject(int val)
   {
        S::shared = val;
        std::cout << "In two -> " << S::shared << "\n";
   }
};

MyObject t(10);

编译器似乎对是否 MyObject t(); 感到困惑是全局范围内的变量声明或函数声明,并将其视为函数声明。

#include "main.hpp" 
#include <iostream>  

class MyObject {     
    public:     
        MyObject(){         
            std::cout << "In two -> " << S::shared  << "\n";     
        } 
};  

MyObject* t;

__attribute__((constructor))
void init_two()
{
    t = new MyObject();
}

__attribute__((destructor))
void uninit_two()
{
    delete t;
}

This should produce what is expected. Pointers are used as it is easier to deal with them explicitly in shared objects as regular initialization doesn't happen automatically. If you don't want to use the pointers provide an explicit initialization for your class and call it in the shared library initialzation function.

* EDIT *

I did some additional experimentation and it appears that if you are using the default constructor, use it implicitly and it will be called, if you are using a non-default constructor then as normal.

so you could change your:

MyObject t();

call to:

MyObject t;

and it wil work without the explicit initialization functions being defined.

or

class MyObject {
public:
   MyObject() { /* as before */ };
   MyObject(int val)
   {
        S::shared = val;
        std::cout << "In two -> " << S::shared << "\n";
   }
};

MyObject t(10);

It appears that the compiler gets confused as to whether the MyObject t(); is a variable declaration, or a function declaration at the global scope and treats it as a function declaration.

幸福丶如此 2024-12-07 23:53:57

我立即想到的问题是你必须分开链接单元。静态类成员只是包装在该类的命名空间中的全局成员。

现在,如果您有两个链接单元,例如主程序和共享对象,那么它们很可能都有一个全局 foo,并且它们将是不同的值。

另外,为什么 Two.cpp 中 t 的静态初始化不在共享对象中运行还不清楚,它可能不能保证在共享对象中的某种类型的 main 函数之前发生。

The problem that immediately jumps at me is that you have to separate link units. A static class member is just a global wrapped up in the namespace of that class.

Now, if you have two link units, say you main program and shared object, it is quite possible for both of them to have a global foo, and they would be distinct values.

Also, why the static initialization of t in two.cpp is not run in a shared object is not clear, its probably not guaranteed to happen before some type of main function in the shared object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文