Med kunstig intelligens skaber HP’s nye OmniBook X 14 en unik og skræddersyet brugeroplevelse målrettet dem, der ønsker høj ydeevne og intelligente funktioner
Med andre ord, nej det kan ikke lade sig gøre. (Med mindre WPGrabOptionsStruct er erklæret som en referencetype, hvilket dens navngivning ikke tyder på :-)
hmmm... ok... Er der så en anden måde jeg skal bruge. Jeg en dll funktion, hvor parameteren er en pointer en en struktur (WPGrabOptionsStruct), så det jeg gerne vil opnå, er at kunne kalde den med enten en struktur eller null/nothing/... hvis den ikke behøves....
Hvis din DLL tager en pointer til en struct som parameter, gætter jeg umiddelbart på at du kan erklære: public static int WPGrabSubmitJob(string urlStr, [MarshalAs(UnmanagedType.LPStruct)] WPGrabOptionsStruct? options)
Så har du erklæret strukturen som nullable, og compileren lader dig sende null med som parameter. Samtidig har du i din DLLImport erklæret, at parameteren er en pointer til en struct.
OK, jeg troede faktisk at marshalling funktionen var "smart nok" til at "gøre det rigtige" med en nullable type. En anden måde at opnå det på, kunne være (bemærk, jeg har ikke mulighed for at teste)
Erklær den eksterne funktion som: [DllImport(DLL_NAME, CallingConvention = DLL_CC, CharSet = CharSet.Ansi, EntryPoint = "WPGrabSubmitJob")] private static extern int WPGrabSubmitJobInt(string urlStr, IntPtr options);
Og lav din funktion der kalder den om til: public static int WPGrabSubmitJob(string urlStr, WPGrabOptionsStruct? options) { IntPtr ptr = IntPtr.Zero; try { if ( options != null ) { ptr = Marshal.AllocHGlobal(Marshal.SizeOf(options.Value)); Marshal.StructureToPtr(options.Value,ptr,false); } return WPGrabSubmitJobInt(urlStr,ptr); } finally { if ( ptr != IntPtr.Zero ) Marshal.FreeHGlobal(ptr); } }
Det "føles" mer besværligt end det burde være, så måske er der en nemmere vej. Efter min bedste overbevisning, burde ovenstående dog virke. Du skal selvfølgelig sikre dig at din C funktion rent faktisk tager en pointer til en struktur som parameter.
Mange tak, det virker, men du har helt ret i, at det er noget omstændigt :(. Kan man lave macroer i C# ala #define T(code) noget_kode code noget_kode_efter som er mulig i c++??
Altså: #define test(ting) cout << ting << endl
og så kalde den med test("dette" << " er en " << "test") og så få c++ koden:
cout << "dette" << " er en " << "test" << endl ???
Nej man kan ikke lave makroer i C#. Men du kunne jo lave en generel utility funktion som wrapper konverteringen fra struct til IntPtr; hvis du skal bruge det andre steder end i WPGrabSubmitJob. Evt. lave en container klasse der implementerer IDisposable, så du kan lave en pæn syntax, hvor du kun har brug for en using blok "ekstra" der hvor den skal anvendes.
Ok, det lyder som en god ide. Jeg har bikset følgende sammen:
using System; using System.Runtime.InteropServices;
namespace wpGrabDotNet.DllCode { public class StructToPointer : IDisposable {
public IntPtr ptr = IntPtr.Zero;
public StructToPointer(wpGrabDll.WPGrabOptionsStruct? inputStruct) { if (inputStruct != null) { ptr = Marshal.AllocHGlobal(Marshal.SizeOf(inputStruct.Value)); Marshal.StructureToPtr(inputStruct.Value, ptr, false); } }
public void Dispose() { if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); } } } }
og så kan jeg bruge
using(StructToPointer sPointer = new StructToPointer(options)) { return WPGrabSubmitJobInt(urlStr, sPointer.ptr); }
Hvad synes du om den konstruktion??? For tiden bruger jeg public StructToPointer(wpGrabDll.WPGrabOptionsStruct? inputStruct) i konstruktøren, er der en måde til at gøre den mere generisk på???
public static class StructPointerExtension { public static StructPointer<T> ToIntPtr<T>(this T value) where T : struct { return new StructPointer<T>(value); }
public static StructPointer<T> ToIntPtr<T>(this System.Nullable<T> value) where T : struct { return new StructPointer<T>(value); } }
Så kan du skrive: using(var pOptions = options.ToIntPtr()) return WPGrabSubmitJobInt(urlStr, pOptions);
Her udnyttes en implicit operator + en extension method, og vi får således en meget kort kodestump hvor StructToPointer bruges; som stadig klart udtrykker formålet med koden, når den læses. Du kan bare erstatte extension method'en med en alm. new hvis ikke du bruger C#3.0.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.