0

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

为了解释一下我的情况,我想做一些像共享对象这样的插件。我还没有决定哪种方法最好。

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

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

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

主文件

#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;
}

主文件

class S {
    public:
    static int shared;

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

二.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
4

2 回答 2

1
#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(); 是否存在感到困惑。是变量声明,或全局范围内的函数声明,并将其视为函数声明。

于 2011-08-22T19:17:46.947 回答
0

立即跳到我头上的问题是您必须分离链接单元。静态类成员只是封装在该类名称空间中的全局变量。

现在,如果你有两个链接单元,比如你的主程序和共享对象,它们很可能都有一个 global foo,它们将是不同的值。

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

于 2011-08-22T18:39:58.547 回答