简体   繁体   中英

Variables do not have the same value when passed into shared library functions

I have developed some functions that need to be integrated into already existing C code to update its functionality. To make calling the new functions as simple as possible, I define a container structure carrying all the poiners and data I need, for example

typedef struct parameters
{
    double time;
    int num_sp;
    int num_nodes;
    int dielCount;
    double meshbounds[6];
} Params;

typedef struct FGM_Container
{
    dev_nodes *d_nodes;
    dev_nodes *h_nodes;
    dev_species *d_sp;
    dp_tree *octree;
    dp_params *dp_pars;
    dev_params *d_p;
    Params           p;     /* Parameters */
    Nodes           *n;     /* nodes array */
    int free_dev_flag;
    double guard_range;
    int max_octree_depth;
} fgm_container;

I compiled my functions into a shared library named FGM (.so since I'm working in Linux), provided an header with prototypes to functions to be called from the original code and successfully rebuilt the whole project. However, when execution enters my functions, it seems that variables passed into them do not retain the same value. Here is a very simple example, the code before and after is more complex but this represents the behavior I'm observing:

int fgm_init(fgm_container *fgmc, int verbose);


int main()
{
    int fgm_ok = 0;
    int free_dev_flag;
    double guard_range = 0;
    int max_octree_depth = 5;

    Params p;
    fgm_container fgmc;

    //Set parameters
    p.time = 0;
    p.num_sp = 2;
    p.num_nodes = 500;
    p.dielCount = 1;
    p.meshbounds[0] = -0.019;
    p.meshbounds[1] =  0.0475;
    p.meshbounds[2] = -0.045;
    p.meshbounds[3] =  0.032;
    p.meshbounds[4] = -0.027;
    p.meshbounds[5] =  0.010;

    //Fill FGM container
    fgmc.p = p;
    fgmc.guard_range = guard_range;
    fgmc.max_octree_depth = max_octree_depth;

    //Print original data
    printf("Original data:\n");
    printf("dielCount: %d\n", fgmc.p.dielCount);
    printf("species: %d\n", fgmc.p.num_sp);
    printf("meshb: %lf %lf\n", fgmc.p.meshbounds[0], fgmc.p.meshbounds[1]);


    //Initialize FGM library
    fgm_ok = fgm_init(&fgmc, 2);

    if (fgm_ok != 0)
    {
        printf("FGM initialization failed. Exiting.\n");
        exit(-1);
    }

    return 0;
}


int fgm_init(fgm_container *fgmc, int verbose)
{
    int ok_flag=0;

    //Extract data from FGM container
    Params p = fgmc->p;
    double guard_range = fgmc->guard_range;
    int max_octree_depth = fgmc->max_octree_depth;


    if (verbose > 0) printf("FGM: Initializing...\n");
    printf("species: %d\n", p.num_sp);
    printf("meshb: %lf %lf\n", p.meshbounds[0], p.meshbounds[1]);
    printf("dielCount: %d\n", p.dielCount);
    getchar();  


    //Proceed with other initialization steps...

    return ok_flag;
}

This code outputs on my screen

Original data:
dielCount: 1
species: 2
meshb: -0.019000 0.047500

FGM: Initializing...
dielCount: 28203712
species: 2
meshb: 0.000000 0.000000
dielcount: 28203712

The dielCount value changes every time I launche the code, as if it were a non-initialized variable. Since the various parameters are used in various malloc functions, things get out of hand very quickly and I start getting out of memory errors, among other things. Moreover, I'm having the same outcome if I try to pass the parameters structure itself by value to the initialization function, ie:

int fgm_init(fgm_container *fgmc, Params p, int verbose);


int main()
{
    // Same steps as before...

    //Initialize FGM library
    fgm_ok = fgm_init(&fgmc, p, 2);

    if (fgm_ok != 0)
    {
        printf("FGM initialization failed. Exiting.\n");
        exit(-1);
    }

    return 0;
}


int fgm_init(fgm_container *fgmc, Params p, int verbose)
{
    int ok_flag=0;

    if (verbose > 0) printf("FGM: Initializing...\n");
    printf("species: %d\n", p.num_sp);
    printf("meshb: %lf %lf\n", p.meshbounds[0], p.meshbounds[1]);
    printf("dielCount: %d\n", p.dielCount);
    getchar();  


    //Proceed with other initialization steps...

    return ok_flag;
}

I would like to point out that the shared library has been verified to execute correctly, with a separate but small test, before being integrated in the destination project (which is reasonably large).

This error kept me busy for hours as I tried to figure it out and there's clearly something I'm missing. Is there anything I should know about working with shared libraries, as this is the first time I create one myself? Could this be related to compilation, since the original project is compiled with a C compiler and my library with the NVIDIA NVCC compiler (because I also use some CUDA calls, but they come after the troublesome part), which is a C++ compiler for the host code portion? Thanks for any insight provided.

Have you inspected the symbols in your .so file (using nm or similar)? It's possible the names are mangled by the C++ compiler leading to strange things happening in your application.

Adding extern "C" around your structs may solve your problem. eg:

extern "C" {
    typedef struct parameters
    {
        double time;
        int num_sp;
        int num_nodes;
        int dielCount;
        double meshbounds[6];
    } Params;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM