45067


お世話になります。  
今、Cで作成されたとあるDLLをC#から利用できるようにしたいと思っているのですが、DLLの関数を呼ぶ際の構造体の作成で困っています。  
なお、DLLの文字コードはUnicodeです。  
C言語のヘッダファイルで、構造体の部分を見ると、1つだけTCHARが指定されており、後はcharが指定されている状態です。  
また、TCHARの部分のサイズは256バイト、CHARの部分のサイズは512バイトで宣言されています。  
下記にCのヘッダファイルの抜粋を記載します。

[code]

    #define STR_MAX_LENGTH      512
    #ifdef _UNICODE
    #define FILENAME_MAX_LENGTH 256
    #else
    #define FILENAME_MAX_LENGTH 512
    #endif
    
    typedef struct {
      TCHAR             name[FILENAME_MAX_LENGTH];
      char              error[STR_MAX_LENGTH];
    } FILE_INFO;
    
[/code]

このような構造体をC#で再現するにはどうしたらよいのでしょうか。  
ちなみに、下記が現在私が作成した構造体の部分の抜粋になりますが、これだとうまく結果が入らないようです。

[code]

    public const int FILENAME_MAX_LENGTH = 256;
    public const int STR_MAX_LENGTH = 512;
    
    [StructLayout(LayoutKind.Sequential, Pack=4)]
    public struct FileInfo{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FILENAME_MAX_LENGTH)]
    public string Name;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = STR_MAX_LENGTH)]
    public string Error;
    
[/code]

なお、DLLの呼び出し部分ではCharSetにUnicodeを指定しております。  
上記のような場合で、構造体をうまく作成する方法はないでしょうか。  
何かアドバイス等があれば、教えていただけると幸いです。  
よろしくお願いいたします。


CC BY-SA 4.0
2018-06-25T15:34:43.650
45061
2018-06-26T01:28:01.037
2018-06-26T01:28:01.037
4236
29034
question
c#
C#でCで書かれたDLLを呼ぶ際の構造体の宣言について


１つの構造体の中でUnicode / ANSIを共存させられないようです。例えばUnicode / Ansiで型を分けるのはどうでしょうか？

[code]

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct Name {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string Value;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Error {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
        public string Value;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct FileInfo {
        public Name Name;
        public Error Error;
    }
    
[/code]

もしくは一方は`string`型を諦めて配列で受け取るとか。

[code]

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct FileInfo {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string Name;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] Error;
    }
    
[/code]

また`unsafe`が必要になりますが、[固定サイズバッファー](https://docs.microsoft.com/ja-
jp/dotnet/csharp/programming-guide/unsafe-code-pointers/fixed-size-
buffers)も使えます。

[code]

    [StructLayout(LayoutKind.Sequential)]
    public unsafe struct FileInfo {
        public fixed char Name[256];
        public fixed byte Error[512];
    }
    
[/code]


CC BY-SA 4.0
2018-06-25T22:51:55.470
45067
2018-06-25T22:51:55.470
4236
45061
answer