c# - Workaround to add a default parameterless constructor to a struct -


let me describe problem - have struct wraps unmanaged handle (let's call mem). need handle call particular method (say "retain" or alternatively, maintain reference count) whenever copied.

in other words, need struct maintains reference count internally (i have mechanism externally well, need way invoke mechanism).

unfortunately, c# doesn't let me in way.

i cannot make mem class because pass array of these structs unmanaged code , not want convert them 1 one before passing them in (just pin , pass).

does know of workaround (il weaving, etc) can applied add behavior in? believe il doesn't prevent me doing this, c#, correct?

i happy answer questions framework , restrictions have, not looking - "please change design" or "don't use c# this" answers, much.

edit: hosted work answer on github: nopencl library.

based on comment, determined following appropriate long-term course of action problems being discussed here. apparently problem centers around use of opencl within managed code. need proper interop layer api.

as experiment, wrote managed wrapper large portion of opencl api evaluate viability of safehandle wrap cl_mem, cl_event, , other objects require call clrelease* cleanup. challenging part implementing methods clenqueuereadbuffer can take array of these handles parameter. initial declaration of method looked following.

[dllimport(externdll.opencl)] private static extern errorcode clenqueuereadbuffer(     commandqueuesafehandle commandqueue,     buffersafehandle buffer,     [marshalas(unmanagedtype.bool)] bool blockingread,     intptr offset,     intptr size,     intptr destination,     uint numeventsinwaitlist,     [in, marshalas(unmanagedtype.lparray)] eventsafehandle[] eventwaitlist,     out eventsafehandle @event); 

unfortunately, p/invoke layer not support marshaling array of safehandle objects, implemented icustommarshaler called safehandlearraymarshaler handle this. note current implementation not use constrained execution regions, asynchronous exception during marshaling can cause leak memory.

internal sealed class safehandlearraymarshaler : icustommarshaler {     private static readonly safehandlearraymarshaler instance = new safehandlearraymarshaler();      private safehandlearraymarshaler()     {     }      public static icustommarshaler getinstance(string cookie)     {         return instance;     }      public void cleanupmanageddata(object managedobj)     {         throw new notsupportedexception();     }      public void cleanupnativedata(intptr pnativedata)     {         if (pnativedata == intptr.zero)             return;          gchandle managedhandle = gchandle.fromintptr(marshal.readintptr(pnativedata, -intptr.size));         safehandle[] array = (safehandle[])managedhandle.target;         managedhandle.free();          (int = 0; < array.length; i++)         {             safehandle current = array[i];             if (current == null)                 continue;              if (marshal.readintptr(pnativedata, * intptr.size) != intptr.zero)                 array[i].dangerousrelease();         }          marshal.freehglobal(pnativedata - intptr.size);     }      public int getnativedatasize()     {         return intptr.size;     }      public intptr marshalmanagedtonative(object managedobj)     {         if (managedobj == null)             return intptr.zero;          safehandle[] array = (safehandle[])managedobj;         int = 0;         bool success = false;         try         {             (i = 0; < array.length; success = false, i++)             {                 safehandle current = array[i];                 if (current != null && !current.isclosed && !current.isinvalid)                     current.dangerousaddref(ref success);             }              intptr result = marshal.allochglobal(array.length * intptr.size);             marshal.writeintptr(result, 0, gchandle.tointptr(gchandle.alloc(array, gchandletype.normal)));             (int j = 0; j < array.length; j++)             {                 safehandle current = array[j];                 if (current == null || current.isclosed || current.isinvalid)                 {                     // memory element initialized null allochglobal                     continue;                 }                  marshal.writeintptr(result, (j + 1) * intptr.size, current.dangerousgethandle());             }              return result + intptr.size;         }         catch         {             int total = success ? + 1 : i;             (int j = 0; j < total; j++)             {                 safehandle current = array[j];                 if (current != null)                     current.dangerousrelease();             }              throw;         }     }      public object marshalnativetomanaged(intptr pnativedata)     {         throw new notsupportedexception();     } } 

this allowed me use following interop declaration.

[dllimport(externdll.opencl)] private static extern errorcode clenqueuereadbuffer(     commandqueuesafehandle commandqueue,     buffersafehandle buffer,     [marshalas(unmanagedtype.bool)] bool blockingread,     intptr offset,     intptr size,     intptr destination,     uint numeventsinwaitlist,     [in, marshalas(unmanagedtype.custommarshaler, marshaltyperef = typeof(safehandlearraymarshaler))] eventsafehandle[] eventwaitlist,     out eventsafehandle @event); 

this method declared private expose through method handles numeventsinwaitlist , eventwaitlist arguments according opencl 1.2 api documentation.

internal static eventsafehandle enqueuereadbuffer(commandqueuesafehandle commandqueue, buffersafehandle buffer, bool blocking, intptr offset, intptr size, intptr destination, eventsafehandle[] eventwaitlist) {     if (commandqueue == null)         throw new argumentnullexception("commandqueue");     if (buffer == null)         throw new argumentnullexception("buffer");     if (destination == intptr.zero)         throw new argumentnullexception("destination");      eventsafehandle result;     errorhandler.throwonfailure(clenqueuereadbuffer(commandqueue, buffer, blocking, offset, size, destination, eventwaitlist != null ? (uint)eventwaitlist.length : 0, eventwaitlist != null && eventwaitlist.length > 0 ? eventwaitlist : null, out result));     return result; } 

the api exposed user code following instance method in contextqueue class.

public event enqueuereadbuffer(buffer buffer, bool blocking, long offset, long size, intptr destination, params event[] eventwaitlist) {     eventsafehandle[] eventhandles = null;     if (eventwaitlist != null)         eventhandles = array.convertall(eventwaitlist, @event => @event.handle);      eventsafehandle handle = unsafenativemethods.enqueuereadbuffer(this.handle, buffer.handle, blocking, (intptr)offset, (intptr)size, destination, eventhandles);     return new event(handle); } 

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -