我想使用Omron V4KU的API,这样描述的文档:
原始c#代码:
const string DllLocation = @"..\..\Libs\Omron\OMCR.dll";
[DllImport(DllLocation)]
public static extern LPCOMCR OMCR_OpenDevice(string lpcszDevice, LPCOMCR_OPTION lpcOption);
public void Start()
{
var lpcOption = new LPCOMCR_OPTION();
var result = OMCR_OpenDevice(null, lpcOption); // error method's type signature is not pinvoke compatible
}
[StructLayout(LayoutKind.Sequential)]
public struct LPCOMCR
{
public string lpcszDevice;
public IntPtr hDevice;
public uint lpcDevice;
}
[StructLayout(LayoutKind.Sequential)]
public struct LPCOMCR_OPTION
{
public uint dwReserved0;
public uint dwReserved1;
public uint dwReserved2;
public uint dwReserved3;
}
如果我在编写代码时遗漏或错误? 对不起,我的英语不好。谢谢你的帮助。
答案 0 :(得分:3)
首先正确定义联合结构:
// OMCR_OPTION.COM
[StructLayout(LayoutKind.Sequential)]
public struct OmcrCom
{
public IntPtr Reserved0;
public uint BaudRate;
public uint Reserved1;
public uint Reserved2;
public uint Reserved3;
public IntPtr Reserved1;
public IntPtr Reserved2;
}
// OMCR_OPTION.USB
[StructLayout(LayoutKind.Sequential)]
public struct OmcrUsb
{
public uint Reserved0;
public uint Reserved1;
public uint Reserved2;
public uint Reserved3;
}
// OMCR_OPTION (union of COM and USB)
[StructLayout(LayoutKind.Explicit)]
public struct OmcrOptions
{
[FieldOffset(0)]
public OmcrCom Com;
[FieldOffset(0)]
public OmcrUsb Usb;
}
// OMCR
[StructLayout(LayoutKind.Sequential)]
public struct OmcrDevice
{
public string Device;
public IntPtr DeviceHandle;
public IntPtr DevicePointer;
}
[DllImport(dllName: DllLocation, EntryPoint = "OMCR_OpenDevice"]
public static extern IntPtr OmcrOpenDevice(string type, ref OmcrOptions options);
然后调用方法,例如:
var options = new OmcrOptions();
options.Com.BaudRate = 115200; // or whatever you need to set
var type = "COM"; // is this USB/COM? not sure
OmcrDevice device;
var devicePtr = OmcrOpenDevice(type, ref options);
if (devicePtr == IntPtr.Zero)
device = (OmcrDevice)Marshal.PtrToStructure(devicePtr, typeof(OmcrDevice));
答案 1 :(得分:2)
嗯,首先,文档要求您将LPCOMCR_OPTION
作为指针传递 - 您将其作为值传递。使用ref
应该有所帮助。但是还有另一个问题,那就是返回值 - 再次,你试图把它解释为一个值,而文档说它是一个指针。但是,这比第一个错误要复杂得多 - 据我所知,您唯一的选择是使用C ++ / CLI互操作库,或期望IntPtr
作为返回值。在任何情况下,您都需要通过这种方式处理正确的内存释放。
答案 2 :(得分:2)
你需要这样做:
[StructLayout(LayoutKind.Sequential)]
public struct OMCR
{
[MarshalAs(UnmanagedType.LPStr)]
public string lpcszDevice;
public IntPtr hDevice;
public IntPtr lpcDevice;
}
[StructLayout(LayoutKind.Sequential)]
public struct OMCR_OPTION
{
public uint dwReserved0;
public uint dwReserved1;
public uint dwReserved2;
public uint dwReserved3;
}
[DllImport(DllLocation, CallingConvention = CallingConvention.???,
SetLastError = true)]
public static extern IntPtr OMCR_OpenDevice(string lpcszDevice,
ref OMCR_OPTION lpcOption);
您需要使用适当的调用约定替换CallingConvention.???
。我们无法从问题中看出这是什么。您必须通过阅读头文件找到答案。
返回值是指向OMCR
的指针。完成后,您需要抓住此指针并将其传递给OMCR_CloseDevice
。
要获得OMCR
值,您可以执行以下操作:
OMCR_OPTION Option = new OMCR_OPTION(); // not sure how to initialize this
IntPtr DevicePtr = OMCR_OpenDevice(DeviceType, ref Option);
if (DevicePtr == IntPtr.Zero)
throw new Win32Exception();
OMCR Device = (OMCR)Marshal.PtrToStructure(DevicePtr, typeof(OMCR));