

お世話になります。

クライアントから渡されたDLLを自作のC#プログラムから呼び出したいのですが、  
関数の仕様書がC++で書かれており、  
知識不足から、C＃からの呼び出し方がよくわからずに困っています。

ご指導よろしくお願いします。

//--仕様書（C++で書かれています）

//関数：  
long Sample( FOO * foo );

//FOO構造体メンバ  
Var_1 (型：unsigned char, サイズ16、In）  
Var_2 (型：unsigned char, サイズ24、In）  
Var_3（型：unsigned char, サイズ128、Out）

//--現在のコード--  
//よくわからない点：  
//構造体の宣言と初期化部分。C++でunsigned char * とあるものをC#でByte[N]としていいのかどうか・・  
//FromHexString関数（自作）で16進数文字列をByteに変換している部分。C#の文字列をどう渡せば正直よくわからないです。

[code]

      class CSample
    {
        //DLL「SampleFunc.dll」を呼び出します。引数には構造体FOOを渡します。
        [DllImport("SampleFunc.dll", CallingConvention = CallingConvention.Cdecl)]
        private extern static long SampleFunc(FOO foo);
    
        //構造体の定義
        public struct FOO
        {
            public byte[] Var_1;
            public byte[] Var_2;
            public byte[] Var_3;
        }
    
        public FOO foo;
    
        public CSample()
        {
            //構造体の初期化
            foo.Var_1 = FromHexString("0C08"); //4文字の16進数
            foo.Var_2 = FromHexString("12341234123412341234123412341234"); //32文字の4桁ごとの数字
            foo.Var_3 = new byte[128]; //DLLからの文字列取得ようバッファ。
        }
    
        //文字列を16進数に変換する関数
        private static byte[] FromHexString(string str)
        {
            int length = str.Length / 2;
            byte[] bytes = new byte[length];
            int j = 0;
            for (int i = 0; i < length; i++)
            {
                bytes[i] = Convert.ToByte(str.Substring(j, 2), 16);
                j += 2;
            }
            return bytes;
        }
    
        //DLLを呼び出す関数
        private void ExecSample()
        {
            long ret = SampleFunc(foo); //ret にはエラーコードが入ってしまう。
        }
    }
    
[/code]


CC BY-SA 3.0
2017-05-26T00:47:33.457
35020
2017-05-26T01:39:05.280
23374
question
c# c++
C++で書かれたDLLをC#から呼び出すには


[既定のマーシャリング](https://msdn.microsoft.com/ja-
JP/library/zah6xy75\(v=vs.110\).aspx)や[プラットフォーム呼び出しによるデータのマーシャリング](https://msdn.microsoft.com/ja-
JP/library/fzhhdwae\(v=vs.110\).aspx)が参考になるでしょうか。（ページの左ツリーにある下階層も。）

> //FOO構造体メンバ  
>  Var_1 (型：unsigned char, サイズ16、In）  
>  Var_2 (型：unsigned char, サイズ24、In）  
>  Var_3（型：unsigned char, サイズ128、Out）

に対応するC#コードは

[code]

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Foo {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string Var_1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)] public string Var_2;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Var_3;
    }
    
[/code]

また

> //関数：  
>  long Sample( FOO * foo );

に対応するC#コードですが、C++言語における`long`のサイズは環境依存です。例えば[Visual
C++では`long`は4バイト](https://msdn.microsoft.com/ja-
JP/library/s3f49ktz.aspx)です。ですので[C#言語でも4バイトとなる`int`](https://docs.microsoft.com/ja-
jp/dotnet/articles/csharp/language-reference/keywords/integral-types-
table)を選択する必要があります（C#言語における`long`は8バイトです）。

[code]

    [DllImport("SampleFunc.dll", CallingConvention = CallingConvention.Cdecl)]
    private extern static int SampleFunc(ref FOO foo);
    
[/code]

以上のように正しく宣言してあれば、後は.NET Frameworkランタイムが正しく変換してくれるため特別な操作は必要ありません。

> //FromHexString関数（自作）で16進数文字列をByteに変換している部分。C#の文字列をどう渡せば正直よくわからないです。

質問文にどのような値を渡す必要があるのかが提示されていないので、この点は第三者には不明です。


CC BY-SA 3.0
2017-05-26T01:39:05.280
35023
2017-05-26T01:39:05.280
4236
35020
answer