[英]Am I marshalling this C function correctly in C#?
In C#, I am trying to PInvoke the following C method: 在C#中,我试图P调用以下C方法:
// C code:
BOOL VstSetLineDetail(
tVstHdl pDataHdl, // type is void*
long pLineItemNo,
tVstTransType pTransType, // enum type
tVstTransSubType pTransSubType, // enum type
tVstTransCd pTransCd, // enum type
char *pTransDate,
tVstTaxedGeo *pTaxedGeoFlag, // enum type
double *pExtdAmt,
double *pTotalTax,
double *pCombRate,
char *pUserArea,
tVstTaxingJuris *pTaxingJuris, // enum type
char *pCustExmtCertifNum,
char *pDivCd,
char *pStoreCd,
char *pGLAcct)
I am marshalling it in C# the following way: 我将以以下方式在C#中将其编组:
// C# code:
[DllImport(@"VertexNative\Vst.dll")]
public static extern bool VstSetLineDetail(
[In]IntPtr dataHandle,
[In]long lineItemNumber,
[In]VstTransactionType transactionType, // an enum I defined in C#
[In]VstTransactionSubtype transactionSubtype, // C# enum
[In]VstTransactionCode transactionCode, // C# enum
[In]string transactionDate,
[In]ref VstTaxedGeo taxedGeo, // C# enum
[In]ref double totalAmount,
[In]ref double totalTax,
[In]ref double combinedTaxRate,
[In]string userArea,
[In]ref VstTaxingJurisdiction jurisdiction, // C# enum
[In]string exceptionCertificate,
[In]string divisionCode,
[In]string storeCode,
[In]string generalLedgerAccount);
Calling it always produces a System.AccessViolationException. 调用它总是会产生一个System.AccessViolationException。 I've tried many combinations of values when calling the function, but get no better results. 调用函数时,我尝试了多种值的组合,但没有得到更好的结果。 Can anyone tell me if it looks like I am marshalling the data types correctly? 谁能告诉我我是否在正确整理数据类型?
It would be great if I had access to the C source code so I could debug, but it's a third-party set of DLLs. 如果可以访问C源代码以便进行调试,那就太好了,但这是第三方DLL集。 I can only see the header files. 我只能看到头文件。
The enums in C are: C中的枚举是:
typedef enum
{
eVstTransTypeIgnore = 99, /* Means ignore this parameter */
eVstTransTypeSale = 0,
eVstTransTypePurchase,
eVstTransTypeService,
eVstTransTypeRentalLease,
eVstTransTypeNumElems,
eVstTransTypeFirstElem = eVstTransTypeSale
} tVstTransType;
typedef enum
{
eVstTransSubTypeIgnore = 99, /* Means ignore this parameter */
eVstTransSubTypeNone = 0,
eVstTransSubTypeProperty,
eVstTransSubTypeFreight,
eVstTransSubTypeService,
eVstTransSubTypeRentalLease,
eVstTransSubTypeExpense,
eVstTransSubTypeMisc,
eVstTransSubTypeNumElems,
eVstTransSubTypeFirstElem = eVstTransSubTypeNone
} tVstTransSubType;
typedef enum
{
eVstTransCdIgnore = 99, /* Means ignore this parameter */
eVstTransCdNormal = 0,
eVstTransCdAdjustment,
eVstTransCdTaxOnlyDebit,
eVstTransCdTaxOnlyCredit,
eVstTransCdDistributeRate,
eVstTransCdDistributeTax,
eVstTransCdNumElems,
eVstTransCdFirstElem = eVstTransCdNormal
} tVstTransCd;
typedef enum
{
eVstTaxedGeoNone = 0,
eVstTaxedGeoDetermine,
eVstTaxedGeoShipTo,
eVstTaxedGeoShipFrom,
eVstTaxedGeoOrderAccept,
eVstTaxedGeoNumElems,
eVstTaxedGeoFirstElem = eVstTaxedGeoNone
} tVstTaxedGeo;
typedef enum {
eVstTaxingJurisPrimary,
eVstTaxingJurisAddtl,
eVstTaxingJurisNumElems,
eVstTaxingJurisFirstElem = eVstTaxingJurisPrimary
} tVstTaxingJuris;
And I've defined them in C# as: 我在C#中将它们定义为:
public enum VstTransactionType
{
Sale,
Purchase,
Service,
RentalLease,
Ignore = 99
}
public enum VstTransactionSubtype
{
None,
Property,
Freight,
Service,
RentalLease,
Expense,
Misc,
Ignore = 99
}
public enum VstTransactionCode
{
Normal,
Adjustment,
TaxOnlyDebit,
TaxOnlyCredit,
DistributeRate,
DistributeTax,
Ignore = 99
}
public enum VstTaxedGeo
{
None,
Determine,
ShipTo,
ShipFrom,
OrderAccept
}
public enum VstTaxingJurisdiction
{
Primary,
Additional
}
No, it's not right, because long
in C isn't 8 bytes like it is in C# (it's often 4 bytes). 不,这是不对的,因为C中的long
不像C#中的8个字节(通常为4个字节)。 Also, a char*
isn't necessarily a string
, because string
s are meant to be immutable, and you can only safely marshal them to const char*
, since only that can guarantee that the C code won't modify them. 另外, char*
不一定是string
,因为string
s是不可变的,并且您只能安全地将它们编组为const char*
,因为只有这样才能保证C代码不会修改它们。 If you need to make them mutable, use StringBuilder
instead of string
, and use [MarshalAs(UnmanagedType.LPTStr)]
or the like. 如果需要使它们可变,请使用StringBuilder
而不是string
,并使用[MarshalAs(UnmanagedType.LPTStr)]
等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.