2010-12-14 8 views
2

In C# Ich versuche, die folgende C-Methode PInvoke:Ordne ich diese C-Funktion in C# korrekt an?

// 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); 

Nennt es immer eine System.AccessViolationException produziert:

// 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) 

ich es in C# die folgende Art und Weise bin Rangier. Ich habe viele Kombinationen von Werten ausprobiert, wenn ich die Funktion aufgerufen habe, bekomme aber keine besseren Ergebnisse. Kann mir jemand sagen, ob es so aussieht, als würde ich die Datentypen korrekt sortieren?

Es wäre großartig, wenn ich Zugriff auf den C-Quellcode hätte, so dass ich debuggen könnte, aber es ist eine DLL von Drittanbietern. Ich kann nur die Header-Dateien sehen.

Die Aufzählungen in 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; 

Und ich habe sie in C# wie folgt definiert:

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 
} 
+0

Sie werden die entsprechenden C und C# Strukturen auch veröffentlichen müssen. Da sie von Wert übergeben werden, ist es wahrscheinlich, dass die Größen der beiden Strukturen nicht genau gleich sind, und dies führt zur Beschädigung dieses Arguments sowie aller folgenden Argumente. – cdhowie

+0

Erwartet Ihre C-Funktion Unicode- oder Ansi-Zeichenfolgen? Außerdem brauchst du hier nicht wirklich "[In]" zu sagen. –

+0

Ich habe die Definitionen für die Enums in C und C# hinzugefügt. Anton, wo sehe ich nach, ob Unicode erwartet wird? –

Antwort

4

Nein, es ist nicht richtig, denn long in C nicht mehr als 8 Bytes wie ist Es ist in C# (es ist oft 4 Bytes). Auch ein char* ist nicht unbedingt ein string, weil string s sind unveränderlich, und Sie können nur sicher marschieren sie auf const char*, da nur das kann garantieren, dass der C-Code sie nicht ändern wird. Wenn Sie sie veränderbar machen müssen, verwenden Sie StringBuilder anstelle von string und verwenden Sie [MarshalAs(UnmanagedType.LPTStr)] oder dergleichen.

+0

Also statt lange sollte ich int gehen? –

+0

Ja, vorausgesetzt, Ihr C-Compiler verwendet 32 ​​Bits für 'long' (was oft der Fall ist). Außerdem ist 'char *' normalerweise ANSI, daher sollten Sie [MarshalAs (UnmanagedType.LPStr)] für diese Parameter verwenden. – Mehrdad

+0

Eine kleine Randnotiz, aber ich denke, es ist erwähnenswert, dass die Frage, ob Sie einen Fehler erhalten, auf einem 64-Bit-System tatsächlich anders ist, weil Parameter übergeben werden ... wenn die Parameter beispielsweise in Registern übergeben werden (was meiner Meinung nach bei den ersten paar Argumenten in einer 64-Bit-Umgebung passiert), könnten Sie keine Fehler in dieser Architektur bekommen, aber Sie könnten in einer anderen auftreten. Sei vorsichtig damit. – Mehrdad

Verwandte Themen