3

さて、これは長いものになります、事前にお詫び申し上げます。=)

ここで使用されているコードは、機密保持の理由から、残念ながら実際の製品コードと正確には一致していませんが、問題、いくつかのテスト済みの解決策を説明し、議論を容易にするために構築されていることを指摘する必要があります。概念レベルでは、すべてが削除されて簡略化されていますが、十分に似ています。データ保護は、実際には必要ですが、ここでは無視されています。

問題

Adaコードから生成された共有オブジェクト「data_provider」があります。Data_providerには内部データレコードがあり、これも(異なる)Adaコードから生成された多数の共有オブジェクト'data_user'1からnからアクセスする必要があります。これらは型defを含むAda仕様を共有しますが、パフォーマンス上の理由から、基本的にデータは共有オブジェクトの境界を越えて共有する必要があります。

これらの共有オブジェクトは、コンパイル時または実行時にlibdl(これはまだ石で書かれていません)を介してc ++メインプログラム(ここでは「ラッパー」と呼ばれます)にリンクされているため、ソリューションはどちらの方法でも機能する必要があります。完全な型defが利用できない場合でも、c++側からもデータを検査できると有益であると付け加えておきます。

-05はピンチで機能する可能性がありますが、コードはAda95コンパイルに合格する必要がある可能性があります。-12はテーブルから外れています。プラットフォームはRHEL5のGNATです。

私が試したもの

現在、「機能する」ソリューションは、データレコードのアドレスを取得し、それをラッパーに渡し、data_userオブジェクトに渡し、アドレス->アクセスを変換し、ポインティデータを内部オブジェクトにコピーすることです。これは、以下のサンプルコードで実装されているメソッドです。ただし、余分なコピーはパフォーマンスの面で問題になる可能性があります。

'動作する'別のテスト済みの方法は、data_providerに変数をエクスポートさせ、data_usersに同じものをインポートさせることですが、これには、コンパイル時にすべてをリンクする必要があり、データをグローバルに公開するため、もろいのは言うまでもなく、かなり汚い感じがします。

条項for data'address use addrは、精緻化時に住所を知る必要があるため、機能しないと思います。

他のいくつかのことは試されて破棄されましたが、私は今のところそれらをテーブルから外しておきます。

以下のコードと組み合わせると、いくつかの提案を得るのに十分であることを願っています。ぜひ聞きたいです。何か説明が必要な場合は、それを求めてください。=)

私は実際、私がただ気が狂っていて、ここで明白な何かを見逃していることを望んでいます。そして、私は、この混乱全体が、Adaやその他の方法で、優れたコーディング慣行に完全に準拠していないことを認識していますが、それでも私はそれに固執しています。

wrapper.cpp

extern "C"  {
    void update_data( int fa, int fb );
    int get_address( void );
    void set_address( int addr );
    void handle_new_data( void );
}

int main( int argc, char** argv ) {
    int addr;
    addr = get_address();
    set_address( addr );
    for (int i = 0; i < 42; i++) {
        update_data( i, -i );
        handle_new_data();
    }
}

data_types.ads

package data_types is

    -- dummy data type
    -- SIMPLIFIED from actual use case
    type data_t is
        record
            field_a : integer := 16#c0ffee#;
            field_b : integer := 16#c0ffee#;
        end record;

    for data_t use
        record
            field_a at 0 range 0..31;
            field_b at 4 range 0..31;
        end record;

    type data_t_ptr is access data_t;

end data_types; 

data_provider.ads

with    system,
        data_types;
use     system,
        data_types;

package data_provider is
    -- update internal data structure
    -- SIMPLIFIED from actual use case
    procedure update_data
        (   fa : in integer;
            fb : in integer );
    pragma export_procedure
    (   internal => update_data,
        external => "update_data" );


    -- return address to record containing data
    function get_address return system.address;
    pragma export_function
    (   internal => get_address,
        external => "get_address" );

    -- 'dummy' data; this needs to be passed to data_user
    data : data_t;

end data_provider;    

data_provider.adb

with    system;
use     system;

package body data_provider
is
    procedure update_data
        (   fa : in integer;
            fb : in integer )
    is
    begin
        data.field_a := fa;
        data.field_b := fb;
    end ;


    function get_address return system.address
    is
    begin
        return data'address;
    end;

end data_provider; 

data_user.ads

with    system,
        data_types;
use     system,
        data_types;

package data_user
is
    -- set address for the data record
    procedure set_address
        (   addr : system.address );
    pragma export_procedure
        (   internal => set_address,
            external => "set_address" );

    -- use the new data in internal data structure
    -- SIMPLIFIED from actual use case
    procedure handle_new_data;
    pragma export_procedure
        (   internal => handle_new_data,
            external => "handle_new_data" );

    -- 'dummy' data; this needs to be passed from data_provider
    data : data_t;

end data_user;

data_user.adb

with    system,
        unchecked_conversion,
        data_types;
use     system,
        data_types;

package body data_user
is

    function to_ptr is new unchecked_conversion
        (   source => system.address,
            target => data_t_ptr );

    -- set address for the data record
    procedure set_address
        (   addr : system.address )
    is
        ptr : data_t_ptr;
    begin
        ptr := to_ptr( addr );
        data := ptr.all;
    end;

    -- use the new data in internal data structure
    -- SIMPLIFIED from actual use case
    procedure handle_new_data
    is
    begin
        null;
    end;

end data_user;

TLDR

Adaで記述され、C ++から外部から呼び出される複数の共有ライブラリは、できればコピーせずに、Adaレコードに格納されている同じデータにアクセスする必要があります。それ、どうやったら出来るの?

4

1 に答える 1

4

データがユーザーにコピーされる唯一の場所はにありますData_User.Set_AddressData_Provider.Update_Dataコピーを変更するための呼び出しData_Providerですが、どのユーザーにも影響はありません。

Set_Addressポインタを保存してからそれをHandle_New_Data読み取ってみませんか?

package data_user
is

   --  as before

   data_ptr : data_t_ptr;

end data_user;

.......
package body data_user
is

   .....

   -- set address for the data record
   procedure set_address
     (   addr : system.address )
   is
   begin
      data_ptr := to_ptr( addr );
   end;

   procedure handle_new_data
   is
   begin
      -- work with data_ptr.all
   end;

end data_user;

ちなみに、この仕事System.Address_To_Access_Conversionsではなく、を使用する必要があります。Unchecked_Conversion

于 2012-09-07T22:03:29.300 に答える