2

機能を更新するために既存の C コードに統合する必要がある関数をいくつか開発しました。新しい関数をできるだけ簡単に呼び出すために、必要なすべてのポインターとデータを保持するコンテナー構造を定義します。たとえば、

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;

関数を FGM (Linux で作業しているため .so) という名前の共有ライブラリにコンパイルし、元のコードから呼び出される関数のプロトタイプを含むヘッダーを提供し、プロジェクト全体を正常に再構築しました。ただし、実行が関数に入ると、関数に渡された変数が同じ値を保持していないようです。これは非常に単純な例です。前後のコードはより複雑ですが、これは私が観察している動作を表しています。

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

このコードは私の画面に出力されます

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

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

初期化されていない変数のdielCountように、コードを起動するたびに値が変化します。さまざまなパラメーターがさまざまな malloc 関数で使用されるため、物事はすぐに手に負えなくなり、メモリ不足エラーなどが発生し始めます。さらに、パラメーター構造体自体を値で初期化関数に渡そうとすると、同じ結果になります。つまり、次のようになります。

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

共有ライブラリは、目的のプロジェクト (かなり大きい) に統合される前に、別の小規模なテストで正しく実行されることが検証されていることを指摘したいと思います。

このエラーは、私がそれを理解しようとしたときに何時間も忙しくし、明らかに何かが欠けていました。共有ライブラリを自分で作成するのはこれが初めてなので、共有ライブラリの操作について知っておくべきことはありますか? 元のプロジェクトは C コンパイラでコンパイルされ、私のライブラリは NVIDIA NVCC コンパイラでコンパイルされているため、これはコンパイルに関連している可能性があります (CUDA 呼び出しもいくつか使用しますが、面倒な部分の後に来るため)。ホストコード部分?提供された洞察に感謝します。

4

1 に答える 1