私はVideo4Linux抽象化と対話する必要があるアプリケーションを開発しています。このアプリケーションは、モノフレームワークを使用してC#で開発されています。P/Invoke ioctlシステムコール
私が直面している問題は、ioctl
システムコールをP/Invokeできないことです。または、より正確には、私はP/Invokeすることができますが、それはひどくクラッシュします。
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
private extern static int KernelIoCtrl(int fd, int request, IntPtr data);
これまでのところは良い:
extern宣言は次のようです。
KernelIoCtrl
を使用して、実際のルーチンは次のとおりです。
protected virtual int Control(IoSpecification request, object data)
{
GCHandle dataHandle;
IntPtr dataPointer = IntPtr.Zero;
try {
// Pin I/O control data
if (data != null) {
dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
dataPointer = dataHandle.AddrOfPinnedObject();
}
// Perform I/O control
int result = KernelIoCtrl(mFileDescriptor, request.RequestCode, dataPointer);
int errno = Marshal.GetLastWin32Error();
// Throw exception on errors
if (errno != (int)ErrNumber.NoError)
throw new System.ComponentModel.Win32Exception(errno);
return (result);
} finally {
if (dataPointer != IntPtr.Zero)
dataHandle.Free();
}
}
上記のすべてのコードが良いようです。クラスIoSpecification
ヘッダ仕様次のI/O要求コードを計算するために使用される(基本的にはマクロ_IOC
が/usr/include/linux/asm/ioctl.h
で宣言以下
data
パラメータであり、以下のように宣言された構造:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Capability
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Driver;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Device;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string BusInfo;
public UInt32 Version;
public CapabilityFlags Capabilities;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public UInt32[] Reserved;
}
(/usr/include/linux/videodev2.h
で宣言された)次の構造を模倣すべき:クラッシュを持つ前に
struct v4l2_capability {
__u8 driver[16]; /* i.e. "bttv" */
__u8 card[32]; /* i.e. "Hauppauge WinTV" */
__u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */
__u32 version; /* should use KERNEL_VERSION() */
__u32 capabilities; /* Device capabilities */
__u32 reserved[4];
};
を、問題がありましたIOCTL要求コードの計算、およびKernelIoCtrl
が期待どおりに機能していた(errno
を返すのはEINVAL)。バグを修正したとき(そして実際に正しいIOCTRL要求コードを持っているとき)、コールはクラッシュを引き起こし始めました。
結論としては、マーシャリングの構造に問題があるようですが、何がうまくいかないのか分かりません。
int ioctl(int d, int request, ...);
しかし、私はint ioctl(int d, int request, void*);
上記のようなルーチンを宣言するコードをたくさん見ました:のioctlルーチンは、次のように宣言されているため
は、私は(男から取られた)、問題は可変引数リストであることを恐れます特定のIOCTRL要求が1つの引数しか取らないようにすることができます。
私はしばらく前に似た何かをしたとのioctlを使用するたびに異なるメソッドの宣言になってしまいました。 'private extern static int KernelIoCtrl(int fd、int request、refケイパビリティ能力);'これはあなたがピン止めをするのを止めるはずです。それでもクラッシュした場合は、構造体宣言が間違っています。 – dtb
@dtbうわー...うまくいった! externsの束を宣言することなく、複数のIOCTL要求を処理する一般的な方法はありますか?そうする方法がなければなりません! – Luca
それを動作させる方法があるかもしれませんが、私はexternsの束を宣言するのが簡単で、はるかに信頼性が高いと思います。 – dtb