Zeiger in C # zum Abrufen von Referenz Von DllImport Funktion
-
23-09-2019 - |
Frage
Ich Bezugnahme auf eine DLL in meinem C # Projekt wie folgt:
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, string cout, string flimit,
string frate, string fwindow, string fincrement, string fbird,
string fparameter, string fvalidation, string fcoupon);
Die FeeCalculation Funktion exportiert wird, wie in der DLL folgt:
extern "C" __declspec(dllexport) void __stdcall FeeCalculation(char *cin,
char *cout, char *flimit, char *frate,
char *fwindow, char *fincrement, char *fbird,
char *fparameter, char *fvalidation, char *fcoupon);
Die DLL-Funktion gibt einen Verweis auf es interne Strukturen in Form von char * so, wenn Sie diese DLL in C ++ verweisen wären, würden Sie die im Anschluss an die Berechnung zu tun, und die zurückgegebenen Strukturen erhalten:
FeeCalculation(buff, (char *)&fans, (char *)fl, (char *)ft, (char *)fw, (char *)fi, (char *)fe, (char *)&fm, (char *)val, (char *)cpn);
Nun, wie rufe ich die Werte, die durch Bezugnahme mit C # zurückgegeben werden? Das heißt, wie kann ich das gleiche tun in C # die zurückgegebenen Strukturen zu bekommen meine zurück Berechnung zu bekommen? Ich weiß, ich brauche eine unsichere Methode zu schaffen, aber ich bin unklar, wie mit den Speicheradressen in C # zu tun, wie Sie es in C ++.
Edit:? Im Folgenden Zustand IntPtr zu verwenden, aber wie stellen Sie in identische Struktur, so dass die Felder der Struktur verwiesen werden können
Edit: Hier ist die zurückgegebene Struktur, dass ich bin an (cout):
struct feeAnswer {
unsigned int fee;
unsigned int tax1;
unsigned int tax2;
unsigned int tax3;
unsigned int tax4;
unsigned int surcharge1;
unsigned int surcharge2;
unsigned int validationFee;
unsigned int couponFee1;
unsigned int couponFee2;
unsigned int couponFee3;
unsigned int couponFee4;
unsigned short int dstay; //Day Stay
unsigned short int mstay; //Minute Stay
};
Hier ist die (cin), dass ich mit anderen Strukturen passieren entlang würde (sie sind Null-Byte in dem Moment, ich will dieses erhalten zuerst zu arbeiten, dann werde ich den Rest implementieren):
struct feeRequest {
unsigned char day;
unsigned char month;
unsigned int year; //2000 ~ 2099
unsigned char hour;
unsigned char minute;
unsigned char rate;
unsigned char validation;
unsigned char coupon1;
unsigned char coupon2;
unsigned char coupon3;
unsigned char coupon4;
};
Lösung
Edit: jetzt, wo wir haben Strukturen zur Arbeit mit, eine bessere Lösung ist möglich. deklarieren nur structs in C #, dass Ihre C ++ structs entsprechen, und sie in der extern-Deklaration verwenden
[StructLayout(LayoutKind.Sequential)]
public struct feeAnswer {
public uint fee;
public uint tax1;
public uint tax2;
public uint tax3;
public uint tax4;
public uint surcharge1;
public uint surcharge2;
public uint validationFee;
public uint couponFee1;
public uint couponFee2;
public uint couponFee3;
public uint couponFee4;
public ushort dstay; //Day Stay
public ushort mstay; //Minute Stay
};
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct feeRequest {
public byte day;
public byte month;
public uint year; //2000 ~ 2099
public byte hour;
public byte minute;
public byte rate;
public byte validation;
public byte coupon1;
public byte coupon2;
public byte coupon3;
public byte coupon4;
};
[DllImport ("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation (
feeRequest cin,
out feeAnswer cout,
...
....
Original-Antwort (bevor wir structs hatten) unter
Es scheint mir, dass diese nicht Verweise auf interne Strings, sondern Zeiger auf String-Puffer, die durch den Aufruf in gefüllt werden. Wenn Sie waren Rückkehr string Zeiger, dann würden diese eher erklärt char**
werden als char*
.
Also ich denke, das sind nur Standard-out-Parameter. Es gibt nur eine Menge von ihnen. So C # Interop würde wie folgt aussehen
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin,
[MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
out string cout,
[MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
out string flimit,
oder diese Option, wenn Ihre "Strings" sind nicht wirklich Strings
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin,
[MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
out byte[] cout,
[MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
out byte[] flimit,
....
Andere Tipps
Die char * Parameter sind in diesem Fall keine Strings, sondern Zeiger auf Stücke von rohem Bytes, die die Daten darstellen. Sie sollten Ihre Parameter als Instanzen des IntPtr-Typs in Verbindung mit Marshal.AllocHGlobal Marschall einen Teil des Speichers zu erstellen und dann Marshal.PtrToStructure dass Speicherblock in einen nutzbaren .NET-Typ zu konvertieren.
Als Beispiel:
[StructLayout(LayoutKind.Sequential)]
struct MyUnmanagedType
{
public int Foo;
public char C;
}
IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyUnmanagedType)));
try
{
FeeCalculation(memory);
MyUnmanagedType result = (MyUnmanagedType)Marshal.PtrToStructure(
memory, typeof(MyUnmanagedType));
}
finally
{
Marshal.FreeHGlobal(memory);
}
Ihre bearbeiten beantworten, müssen Sie eine Struktur schaffen, und verwenden Sie dann die StructLayoutAttribute auf den Feldern, um tat die Byte-Reihenfolge und Klotzen des gleiches wie das Original-dLL zu machen.