gpt4 book ai didi

c# - 如何通过 Visual Studio COM 包装器(或其他方式)在 C# 中使用 C++ 属性 union

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:53:59 27 4
gpt4 key购买 nike

我正在尝试使用制造商提供的 com/dll(用 C++ 编写)与设备通信,但是我遇到了无法在结构中设置字段值的问题。

在 C++ 中,根据提供的文档,这个结构是这样实现的:

typedef struct tagFCITEST
{
FCITESTTYPE TestType;
[switch_type( FCITESTTYPE ), switch_is( TestType )]
union
{
[case(FCI_TYPE_PROPORTIONAL)] FCI_TEST_PROPORTIONAL Test;
[case(FCI_TYPE_SWITCH)] FCI_TEST_SWITCH SwitchTest;
[default];
};
} FCITEST;

但是,当我在 Visual Studio 中“转到定义”时,我发现了以下内容:

public struct tagFCITEST
{
public __MIDL___MIDL_itf_mftFCINTF_0209_0005 __MIDL_0022;
public tagFCITESTTTYPE TestType;
}

public struct __MIDL___MIDL_itf_mftFCINTF_0209_0005
{
}

显然 C# 不支持这些类型的 union ,看起来 visual studio 在创建包装器时搞砸了,所以我尝试了以下方法来解决这个问题:

    public struct tagFCITEST
{
public MFTFCINTFLib.tagFCITESTTTYPE TestType;
public __MIDL___MIDL_itf_mftFCINTF_0209_0005 __MIDL_0022;
}

[StructLayout(LayoutKind.Explicit)]
public struct __MIDL___MIDL_itf_mftFCINTF_0209_0005
{
[FieldOffset(0)]
public MFTFCINTFLib.tagFCI_TEST_PROPORTIONAL Test;
[FieldOffset(0)]
public MFTFCINTFLib.tagFCI_TEST_SWITCH SwitchTest;
}

如果我在方法调用中使用自定义结构,编译器会不高兴,并告诉我存在无效参数。即使我要创建自定义方法签名:

    [DllImport("mftFCINTF.dll")]
public static extern void DownloadTag(int ISessionID,
string szwDeviceTag,
string szwDeviceSeriaINum,
ref MFTFCINTFLib.tagFCICOMMDEF pCommDef,
ref MFTFCINTFLib.tagFCIDEVIN pInputDef,
ref MFTFCINTFLib.tagFCIDEVOUT pOutputDef,
ref MFTFCINTFLib.tagFCIDEVRELATION pRelationDef,
ref tagFCITEST pTestDef, // This is the changed line
string szwSetupInstructions,
string szwCleanupInstructions,
out string pszwLocationInCalibrator,
out MFTFCINTFLib.tagFCISTATUS pStatus);

未使用签名。有没有办法修改 visual studio 的包装器实现?或者也许有更好的方法来解决这个问题?

谢谢!

编辑:

这是生成的 .IDL 文件

// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: mftFCINTF.dll

[
uuid(C81FC550-84AC-437B-AD0E-DA283ACE4687),
version(1.0),
helpstring("mftFCINTF 1.0 Type Library"),
custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 83951780),
custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1058814716)

]
library MFTFCINTFLib
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");

// Forward declare all types defined in this typelib
interface ICalibratorInfo;
interface ICalibratorDownload;
interface ICalibratorUpload;
interface IConfigurator;

[
uuid(34E98744-678E-4D9A-B57F-6A96521BB609),
helpstring("MFT 1.0 by Meriam Process Technologies")
]
coclass mftFCI {
[restricted] interface ICalibratorInfo;
[restricted] interface ICalibratorDownload;
[restricted] interface ICalibratorUpload;
[restricted] interface IConfigurator;
};

[
odl,
uuid(FF5EFD41-7B15-11D1-B326-00001CBE02AA),
version(1.0),
helpstring("ICalibratorInfo Interface")
]
interface ICalibratorInfo : IUnknown {
HRESULT _stdcall DriverProperties([out] tagFCISTATUS* pStatus);
HRESULT _stdcall Open(
[in] int nPortNumber,
[out] long* plSessionId,
[out] long* plCapabilities,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall Close(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall Properties(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall GetId(
[in] long lSessionId,
[out] LPWSTR* pszwCalManufacturer,
[out] LPWSTR* pszwCalModel,
[out] LPWSTR* pszwCalSerialNum,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall GetCalDates(
[in] long lSessionId,
[out] _SYSTEMTIME* pLastCalDate,
[out] _SYSTEMTIME* pNextCalDueDate,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall SetDateAndTime(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall SetTempStandard(
[in] long lSessionId,
[in] int nTemperatureStd,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall GetTestResultsCount(
[in] long lSessionId,
[out] int* pnCount,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall ClearMemory(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall ValidateTag(
[in] tagFCICOMMDEF* pCommDef,
[in] tagFCIDEVIN* pInputDef,
[in] tagFCIDEVOUT* pOutputDef,
[in] tagFCIDEVRELATION* pRelationDef,
[in] tagFCITEST* pTestDef,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall GetSensorModuleId(
[in] long lSessionId,
long nSensorIndex,
[out] LPWSTR* pszwCalManufacturer,
[out] LPWSTR* pszwCalModel,
[out] LPWSTR* pszwCalSerialNum,
[out] LPWSTR* pszwCalDate,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall ClearCalFatEntry(
[in] long nIndex,
[out, retval] VARIANT_BOOL* pResult);
HRESULT _stdcall SetAppDriverMode([in] long nMode);
};

typedef enum {
FCI_OK = 0,
FCI_FAILED = 1,
FCI_COMM_ERROR = 2,
FCI_REVISION_ERROR = 3,
FCI_CANCELED = 4,
FCI_NOT_SUPPORTED = 5,
FCI_ALREADY_OPEN = 6,
FCI_WRONG_SESSION = 7,
FCI_WRONG_CALIBRATOR = 8,
FCI_ERR_IN_RANGE = 9,
FCI_ERR_IN_UNITS = 10,
FCI_ERR_IN_TYPE = 11,
FCI_ERR_IN_MANUAL = 12,
FCI_ERR_OUT_RANGE = 13,
FCI_ERR_OUT_UNITS = 14,
FCI_ERR_OUT_TYPE = 15,
FCI_ERR_OUT_MANUAL = 16,
FCI_ERR_INOUT = 17,
FCI_ERR_RELATION = 18,
FCI_ERR_PROBE = 19,
FCI_ERR_CJC = 20,
FCI_ERR_ENUM = 21,
FCI_ERR_RESOURCE = 22,
FCI_ERR_TESTPOINT = 23,
FCI_ERR_TESTTYPE = 24,
FCI_ERR_POWER = 25,
FCI_ERR_TAG = 26,
FCI_MEM_FULL = 27,
FCI_MEM_EMPTY = 28,
FCI_MEM_HAS_DATA = 29,
FCI_END_OF_UPLOAD = 30,
FCI_ERR_DOWNLOAD = 31,
FCI_ERR_TAGLENGTH = 32,
FCI_ERR_SNLENGTH = 33,
FCI_ERR_MAXPOINTS = 34,
FCI_END = 35
} tagFCISTATUS;

typedef struct tag_SYSTEMTIME {

unsigned short wYear;

unsigned short wMonth;

unsigned short wDayOfWeek;

unsigned short wDay;

unsigned short wHour;

unsigned short wMinute;

unsigned short wSecond;

unsigned short wMilliseconds;
} _SYSTEMTIME;

typedef struct tagtagFCICOMMDEF {

tagFCICOMMTYPE CommType;

__MIDL___MIDL_itf_mftFCINTF_0209_0001 __MIDL_0016;
} tagFCICOMMDEF;

typedef enum {
FCI_COMMTYPE_NONE = 1,
FCI_COMMTYPE_HART = 2
} tagFCICOMMTYPE;

typedef union tag__MIDL___MIDL_itf_mftFCINTF_0209_0001 {

tagFCI_COMMDEF_HART HartData;
} __MIDL___MIDL_itf_mftFCINTF_0209_0001;

typedef struct tagtagFCI_COMMDEF_HART {

unsigned char cBlockId;

unsigned char cURev;

unsigned char cPollAddr;

unsigned char acUid[5];

unsigned char acTag[6];

unsigned char acDescriptor[12];

unsigned char acDate[3];

unsigned char acMessage[24];
} tagFCI_COMMDEF_HART;

typedef struct tagtagFCIDEVIN {

tagFCIBLOCKTYPE DevType;

__MIDL___MIDL_itf_mftFCINTF_0209_0002 __MIDL_0017;
} tagFCIDEVIN;

typedef enum {
FCI_BLKTYPE_GENERIC = 1,
FCI_BLKTYPE_TEMP_RTD = 2,
FCI_BLKTYPE_TEMP_TC = 3,
FCI_BLKTYPE_FREQUENCY = 4,
FCI_BLKTYPE_PRESSURE = 5,
FCI_BLKTYPE_TEMP_MEASRTD = 6,
FCI_BLKTYPE_TEMP_MEASTC = 7,
FCI_BLKTYPE_HART = 8,
FCI_BLKTYPE_SWITCH = 9,
FCI_BLKTYPE_DIFFTEMP = 10
} tagFCIBLOCKTYPE;

typedef union tag__MIDL___MIDL_itf_mftFCINTF_0209_0002 {

tagFCI_BLKDEF_PRESSURE PressureData;

tagFCI_BLKDEF_RTD TempRtdData;

tagFCI_BLKDEF_TC TempTcData;

tagFCI_BLKDEF_RTD TempMeasRtdData;

tagFCI_BLKDEF_TC TempMeasTcData;

tagFCI_BLKDEF_FREQUENCY FrequencyData;

tagFCI_BLKDEF_HART HartData;

tagFCI_BLKDEF_DIFFTEMP DiffTempData;

tagFCI_BLKDEF_GENERIC GenericData;
} __MIDL___MIDL_itf_mftFCINTF_0209_0002;

typedef struct tagtagFCI_BLKDEF_PRESSURE {

single rURV;

single rLRV;

single rSettling;

unsigned short wUnits;

unsigned short wPressureType;
} tagFCI_BLKDEF_PRESSURE;

typedef struct tagtagFCI_BLKDEF_RTD {

single rURV;

single rLRV;

single rSettling;

unsigned short wUnits;

unsigned short wProbeType;

unsigned short wNumWires;

unsigned short wRESERVED;
} tagFCI_BLKDEF_RTD;

typedef struct tagtagFCI_BLKDEF_TC {

single rURV;

single rLRV;

single rSettling;

single rManualCJC;

unsigned short wUnits;

unsigned short wProbeType;

unsigned short wCJC;

unsigned short wProbeConnect;
} tagFCI_BLKDEF_TC;

typedef struct tagtagFCI_BLKDEF_FREQUENCY {

single rURV;

single rLRV;

single rSettling;

single rAmplitude;

unsigned short wUnits;

unsigned short wWaveForm;
} tagFCI_BLKDEF_FREQUENCY;

typedef struct tagtagFCI_BLKDEF_HART {

single rUSL;

single rLSL;

single rSettling;

unsigned short wUnits;
} tagFCI_BLKDEF_HART;

typedef struct tagtagFCI_BLKDEF_DIFFTEMP {

single rURV;

single rLRV;

single rSettling;

unsigned short wUnits;

unsigned short wDeviceVariable1;

unsigned short wDeviceVariable2;
} tagFCI_BLKDEF_DIFFTEMP;

typedef struct tagtagFCI_BLKDEF_GENERIC {

single rURV;

single rLRV;

single rSettling;

unsigned short wUnits;
} tagFCI_BLKDEF_GENERIC;

typedef struct tagtagFCIDEVOUT {

tagFCIBLOCKTYPE DevType;

__MIDL___MIDL_itf_mftFCINTF_0209_0003 __MIDL_0018;
} tagFCIDEVOUT;

typedef union tag__MIDL___MIDL_itf_mftFCINTF_0209_0003 {

tagFCI_BLKDEF_PRESSURE PressureData;

tagFCI_BLKDEF_RTD TempMeasRtdData;

tagFCI_BLKDEF_TC TempMeasTcData;

tagFCI_BLKDEF_FREQUENCY FrequencyData;

tagFCI_BLKDEF_HART HartData;

tagFCI_BLKDEF_SWITCH Switch;

tagFCI_BLKDEF_GENERIC GenericData;
} __MIDL___MIDL_itf_mftFCINTF_0209_0003;

typedef struct tagtagFCI_BLKDEF_SWITCH {

unsigned short wContactType;

unsigned short wForm;

unsigned short wTripDirection;

single rWetContactVoltage;
} tagFCI_BLKDEF_SWITCH;

typedef struct tagtagFCIDEVRELATION {

tagFCIRELATIONTYPE RelType;

__MIDL___MIDL_itf_mftFCINTF_0209_0004 __MIDL_0020;
} tagFCIDEVRELATION;

typedef enum {
FCI_RELTYPE_LINEAR = 0,
FCI_RELTYPE_SQRT = 1,
FCI_SQRT_3RD_PWR = 2,
FCI_SQRT_5TH_PWR = 3,
FCI_RELTYPE_TABLE = 4,
FCI_RELTYPE_SWITCH = 230
} tagFCIRELATIONTYPE;

typedef union tag__MIDL___MIDL_itf_mftFCINTF_0209_0004 {

tagFCI_RELDEF_SQRT SqrtData;

tagFCI_RELDEF_TABLE TableData;
} __MIDL___MIDL_itf_mftFCINTF_0209_0004;

typedef struct tagtagFCI_RELDEF_SQRT {

single rBreakPoint;
} tagFCI_RELDEF_SQRT;

typedef struct tagtagFCI_RELDEF_TABLE {

unsigned short wNumPoints;

unsigned short wInterpolate;

single rInput[30];

single rOutput[30];
} tagFCI_RELDEF_TABLE;

typedef struct tagtagFCITEST {

tagFCITESTTTYPE TestType;

__MIDL___MIDL_itf_mftFCINTF_0209_0005 __MIDL_0022;
} tagFCITEST;

typedef enum {
FCI_TYPE_PROPORTIONAL = 1,
FCI_TYPE_SWITCH = 2
} tagFCITESTTTYPE;

typedef union tag__MIDL___MIDL_itf_mftFCINTF_0209_0005 {

tagFCI_TEST_PROPORTIONAL Test;

tagFCI_TEST_SWITCH SwitchTest;
} __MIDL___MIDL_itf_mftFCINTF_0209_0005;

typedef struct tagtagFCI_TEST_PROPORTIONAL {

unsigned short wRESERVED;

unsigned short wPowerSource;

unsigned short wCalSourceInput;

unsigned short wCalReadInput;

unsigned short wCalMeasureOutput;

unsigned short wNumTestPoints;

single arTestPoint[21];

single rTestPointTolerance;

single rAdjustmentLimit;

single rMaxErrorLimit;
} tagFCI_TEST_PROPORTIONAL;

typedef struct tagtagFCI_TEST_SWITCH {

single rTripSetPoint;

single rTripTolerance;

single rResetDeadband;

single rDeadbandTolerance;

single rRampTime;

long bTestReset;
} tagFCI_TEST_SWITCH;

[
odl,
uuid(FF5EFD42-7B15-11D1-B326-00001CBE02AA),
version(1.0),
helpstring("ICalibratorDownload Interface")
]
interface ICalibratorDownload : IUnknown {
HRESULT _stdcall StartDownloading(
[in] long lSessionId,
[in] LPWSTR szSessionName,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall DownloadTag(
[in] long lSessionId,
[in] LPWSTR szwDeviceTag,
[in] LPWSTR szwDeviceSerialNum,
[in] tagFCICOMMDEF* pCommDef,
[in] tagFCIDEVIN* pInputDef,
[in] tagFCIDEVOUT* pOutputDef,
[in] tagFCIDEVRELATION* pRelationDef,
[in] tagFCITEST* pTestDef,
[in] LPWSTR szwSetupInstructions,
[in] LPWSTR szwCleanupInstructions,
[out] LPWSTR* pszwLocationInCalibrator,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall FinishDownloading(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall AbortDownload(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
};

[
odl,
uuid(FF5EFD43-7B15-11D1-B326-00001CBE02AA),
version(1.0),
helpstring("ICalibratorUpload Interface")
]
interface ICalibratorUpload : IUnknown {
HRESULT _stdcall StartUploading(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall UploadNextTag(
[in] long lSessionId,
[out] LPWSTR* pszwLocationInCalibrator,
[out] LPWSTR* pszwDeviceTag,
[out] LPWSTR* pszwDeviceSerialNum,
[out] LPWSTR* pszwTechnician,
[out] LPWSTR* pszwServiceNote,
[out] int* pnTemperatureStd,
[out] tagFCICOMMDEF* pCommDef,
[out] tagFCIRESULT* pAsFound,
[out] tagFCIRESULT* pAsLeft,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall FinishUploading(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall AbortUpload(
[in] long lSessionId,
[out] tagFCISTATUS* pStatus);
HRESULT _stdcall PreviewNextTag(
[in] long lSessionId,
[out] LPWSTR* pszwLocationInCalibrator,
[out] LPWSTR* pszwDeviceTag,
[out] LPWSTR* pszwDeviceSerialNum,
[out] long* plRecordType,
[out] _SYSTEMTIME* pDate,
[out] tagFCISTATUS* pStatus);
};

typedef struct tagtagFCIRESULT {

tagFCITESTTTYPE ResultType;

__MIDL___MIDL_itf_mftFCINTF_0209_0006 __MIDL_0024;
} tagFCIRESULT;

typedef union tag__MIDL___MIDL_itf_mftFCINTF_0209_0006 {

tagFCI_RESULT_PROPORTIONAL Results;

tagFCI_RESULT_SWITCH SwitchResults;
} __MIDL___MIDL_itf_mftFCINTF_0209_0006;

typedef struct tagtagFCI_RESULT_PROPORTIONAL {

double dInputLowerRangeValue;

double dInputUpperRangeValue;

int nInputRangeUnits;

double dOutputLowerRangeValue;

double dOutputUpperRangeValue;

int nOutputRangeUnits;

int nRelationship;

int nNumberOfTestPoints;

double adInput[21];

double adOutput[21];

LPWSTR szwAuxEquipManufacturer;

LPWSTR szwAuxEquipModel;

LPWSTR szwAuxEquipSerialNum;

double dAmbientTemperature;

int nAmbientTemperatureUnits;

_SYSTEMTIME TestDate;
} tagFCI_RESULT_PROPORTIONAL;

typedef struct tagtagFCI_RESULT_SWITCH {

unsigned short wUnits;

single rTripPoint;

single rResetPoint;

unsigned short bResetTested;

_SYSTEMTIME TestDate;

LPWSTR szwAuxEquipManufacturer;

LPWSTR szwAuxEquipModel;

LPWSTR szwAuxEquipSerialNum;
} tagFCI_RESULT_SWITCH;

[
odl,
uuid(084ABD42-30CE-49AD-B1FA-9C869AAD2A27),
version(1.0),
helpstring("IConfigurator Interface")
]
interface IConfigurator : IUnknown {
[helpstring("method UploadConfiguration")]
HRESULT _stdcall UploadConfiguration(
long* pDataAvailabe,
BSTR bstrFilePath,
[in, out] BSTR* pbstrTag,
[in, out] long* plDof,
[in, out] long* plAsFoundAsLeft,
[in, out] long* pnLocation,
[in, out] long* pnMultivar,
[in, out] BSTR* pbstrDeviceSerialNum,
[out, retval] VARIANT_BOOL* pResult);
[helpstring("method DownloadConfiguration")]
HRESULT _stdcall DownloadConfiguration(
[in] BSTR bstrFilePath,
[in, out] long* pnLocation,
[out, retval] VARIANT_BOOL* pResult);
[helpstring("method ClearConfiguratorMemory")]
HRESULT _stdcall ClearConfiguratorMemory();
[helpstring("method GetConfigCount")]
HRESULT _stdcall GetConfigCount([out, retval] long* lCount);
[helpstring("method PreviewConfiguration")]
HRESULT _stdcall PreviewConfiguration(
long* pDataAvailabe,
[in, out] BSTR* pbstrTag,
[in, out] long* plDof,
[in, out] long* plAsFoundAsLeft,
[in, out] long* plOrigin,
[in, out] long* pnLocation,
[in, out] BSTR* pbstrDeviceSerialNum,
[out] _SYSTEMTIME* pDate,
[out, retval] VARIANT_BOOL* pResult);
[helpstring("method SetPortNumber")]
HRESULT _stdcall SetPortNumber(long nPort);
[helpstring("method ClearConfigFatEntry")]
HRESULT _stdcall ClearConfigFatEntry(
long nIndex,
[out, retval] VARIANT_BOOL* pResult);
};
};

最佳答案

毫无疑问,您通过导入 COM 服务器的类型库获得了这些声明。通过添加对 COM dll 的引用或手动运行 Tlbimp.exe。

是的,这是一个问题,类型库只支持可以用 IDL 表达的子集。而这些受歧视的 union 当然不属于其中。它们只对跨单元边界正确编码结构很重要,只有代理/ stub DLL 需要正确查看它们,这是自动生成的代码。

解决问题的两种基本方法,都不是特别令人愉快:

  • 您可以编辑从类型库生成的互操作库并修复结构声明。首先使用 ildasm.exe 反编译 DLL,编辑 IL 并将其与 ilasm.exe 放回一起。您可以使用反编译的示例 C# 程序来查看 IL 的外观。这可行,但重要的是 COM 组件是稳定的,这样您就不必一遍又一遍地执行此操作。有一个 How-To article在描述该过程的 MSDN 中。

  • 用 C++/CLI 语言为组件编写一个包装器。您可以 #include 由 IDL 中的 midl.exe 生成的 .h 文件。显然,只有当您有权访问 IDL 或拥有 .h 文件时,这才有效,如果您没有,则需要联系供应商或作者。这样做的一个好处是您还可以规避其他类型的问题。缺点是您需要了解该语言的基础知识以及使用 C++ 进行 COM 客户端编程的基础知识。

关于c# - 如何通过 Visual Studio COM 包装器(或其他方式)在 C# 中使用 C++ 属性 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12646488/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com