簡體   English   中英

外部“C” C++ 程序中的外部變量作為 class 變量.. 如何聲明它?

[英]extern "C" extern variable in C++ program sought as a class variable.. how to declare it?

我在下面有一個代碼。 它是由 qemu 程序(一個 C 程序)使用 dlopen 加載的動態共享庫的一部分。

extern "C" {
extern uint64_t host_virt_offset;
}

int Driver::CallSetBareMetalMode( uint64_t * args_ptr)
{
    dbg_enter();
    
    (... some codes ..)

    baremetal_axpu_es   = (struct es_t      *)(args_ptr[0] + host_virt_offset);   // line a
    baremetal_axpu_regs = (struct reg_csr_t *)(args_ptr[1] + host_virt_offset);   // line b

    dbg_leave();
    return 0;
}

因為變量host_virt_offset是在qemu(一個C程序)中定義的,所以我認為可以在這個共享庫里面使用沒有問題。 但是當我運行它時,會發生錯誤,當我使用調試器檢查它時,我發現代碼正在尋找Driver::host_virt_offset而不是全局(和外部)變量host_virt_offset 我通過該線附近的下方知道這一點。

(gdb) print host_virt_offset
Missing ELF symbol "AXPU::host_virt_offset".

我嘗試在 a,b 行中使用::host_virt_offset ,但它沒有編譯。 我應該如何聲明和使用變量 host_virt_offset?

ADD:(我有一段時間無法連接到stackoverflow)我制作了一個可重現的程序。 在這里使用我使用的方法可以正常工作。 所以還有別的東西。 '

<< main.c >>

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

uint64_t var_from_qemu = 0x12345678;

int main(void)
{
    void * dlh = dlopen("./libbar.so", RTLD_NOW);
    if (!dlh) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE); 
    }
    void (*bar)(void) = dlsym(dlh,"bar");
    if (!bar) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE); 
    }
    bar();
    return 0;
}

<<bar.cpp>> <-- 共享庫

#include <stdint.h>
#include <stdio.h>

extern "C" {
extern uint64_t var_from_qemu;
}

class BC;

class BC {
public:
    void bar(void);
    BC();
    ~BC();
};

BC::BC()
{
}

BC::~BC()
{
}

void BC::bar(void)
{
    printf("class function : var_from_qemu = %lx\n", var_from_qemu);
}

extern "C" {
void bar(void)
{
printf("global function : var_from_qemu = %lx\n", var_from_qemu);
BC tmp;
tmp.bar();
}
}

<<結果>>

$ g++ bar.cpp -Wall -fpic -shared -g -o libbar.so
$ gcc main.c -o main -g -ldl -rdynamic
$ main
global function : var_from_qemu = 12345678
class function : var_from_qemu = 12345678

extern "C"在聲明變量時沒有區別,它只對函數很重要。 原因是 C++ 中的函數可以重疊,但變量不能。

例如:

#include <iostream>
using namespace std;
extern "C" {
    int n1 = 1;
    
}
int n2 =2;
int main()
{
    cout<<n1<<endl<<n2<<endl;
    return 0;
}

在上面的代碼中, n1n2的訪問方式相同。

這就是我解決它的方法。
我在 class Driver中添加了變量host_virt_offset ,它與 qemu 設置的變量host_virt_offset不同。 我將 extern host_virt_offset復制到 class Driver的變量host_virt_offset ,如下所示。

extern "C" int some_function_during_the_init(...)
{
... some codes ..
AXPU::Driver *axpu_driver = AXPU::Driver::getInstance();
axpu_driver->host_virt_offset = host_virt_offset;   // copy to the class variable
... some codes .. 
}

並且應該像下面這樣更改原始代碼。

extern "C" {
extern uint64_t host_virt_offset;
}

int Driver::CallSetBareMetalMode( uint64_t * args_ptr)
{
    dbg_enter();
    
    (... some codes ..)

    baremetal_axpu_es   = (struct es_t      *)((args_ptr + host_virt_offset/8)[0] + host_virt_offset);     // line a
    baremetal_axpu_regs = (struct reg_csr_t *)((args_ptr + host_virt_offset/8)[1] + host_virt_offset);     // line b


    dbg_leave();
    return 0;
}

Now the host_virt_offset value is correct inside the class member function and print host_virt_offset in gdb command doesn't complain and shows the correct value(I think the gdb is showing the class variable at this code point).
這段代碼向 qemu 客戶物理地址添加了一些偏移量,以將其轉換為主機虛擬地址(即 qemu 程序域地址)。 args_ptr 本身就是來賓物理加法器,所以我也必須將偏移量賦予該值。 (沒有它,seg-fault 會像以前一樣出現。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM