DLL return value - Printable Version -Shoutbox (https://shoutbox.menthix.net) +-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58) +--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4) +---- Forum: Scripting (/forumdisplay.php?fid=39) +----- Thread: DLL return value (/showthread.php?tid=70004) DLL return value by deAd on 12-28-2006 at 07:54 PM
I have a C++ DLL and I'd like to return an array of data. It is stored in a vector inside the DLL, but I don't know how to return it so it can be used in JScript. RE: Calling a DLL (two questions) by J-Thread on 12-28-2006 at 08:59 PM
I am not sure about the first one, but for the second one you should create a .def file containing something like: code: RE: Calling a DLL (two questions) by deAd on 12-28-2006 at 09:02 PM
Should I remove the "__declspec(dllexport)" definitions? RE: DLL return value by CookieRevised on 12-29-2006 at 09:57 AM
Like you use Interop.Call with Windows API's, you need to allocate some memory space in your script first (Interop.Allocate). RE: DLL return value by deAd on 12-29-2006 at 04:28 PM What if you don't know how much space you need? I could create another function that returns a DWORD telling how much space you'd need but it's possible that this value could change between calls (not likely though, as there wouldn't be much of a time gap )... RE: DLL return value by CookieRevised on 12-29-2006 at 05:12 PM
quote:As I explained in the MSN chat, by creating the data in the first function and storing it until the second function has been called. Or by creating the data with the first call and with a specific set of parameters (eg: everything 0, except the buffersize) and storing it until a second call is done with a valid buffer as one of the parameters. Look at the Windows APIs which can return variable sized data... They either consist of actually two APIs, where you first need to call the first API to get the size of the returned data, and then call the second API to get the actual data. Or it is 1 function which you need to call twice. The first time with all the parameters being null, except the buffersize parameter. And the second time with a pointer to the actual buffer. Many times, in the second call they return the length of the written data too. So you, as a caller, can check if how much has been written to the buffer (the returned datalength is non zero). See the registry APIs for example: RegQueryValue which works in exact the same way. Another example, and a slightly different method, but with the same principles (a large enough buffersize must be given, or yuo need to call the function twice to recieve the appropiate buffersize) is done by RegQueryMultipleValues. This API works with an array btw. Also, in your DLL, make sure you first check the size of the actual allocated memory space by the caller. In this check, the given buffersize is of no matter, you need to check the allocated memory size against the size it would require to write all your data to the memory. This is very mandatory so that you don't write beyond the memory space available to your function. ^^ and if you do this properly, you can even make it that the caller must only call your function once, on the condition that the buffer is large enough so the function can directly write all the data to the buffer. If the buffer is not large enough, still write data to the buffer (until the end) and set the return value of your function to ERROR_MORE_DATA or something. thus, for example the user can do: // This will allocate the exact amount of needed memory var BufferSize = 0 var ReturnValue = Interop.Call("your.dll", yourfunc, 0, BufferSize) var Buffer = Interop.Allocate(BufferSize) var ReturnValue = Interop.Call("your.dll", yourfunc, Buffer.DataPtr, BufferSize) ReturnValue is 0 Buffer is filled with BufferSize bytes of data BufferSize is the amount of data bytes in the buffer or // This will allocate more memory than needed var BufferSize = 4096 var Buffer = Interop.Allocate(BufferSize) var ReturnValue = Interop.Call("your.dll", yourfunc, Buffer.DataPtr, BufferSize) ReturnValue is 0 Buffer is filled with x bytes of data BufferSize is the amount of data bytes in the buffer (thus x) or // This will allocate too little memory var BufferSize = 10 var Buffer = Interop.Allocate(BufferSize) var ReturnValue = Interop.Call("your.dll", yourfunc, Buffer.DataPtr, BufferSize) ReturnValue is ERROR_MORE_DATA Buffer is filled with 10 bytes of data BufferSize contains the actual needed bytes PS: as a sidenote, many people use those registry APIs (or any other API which requires a big enough buffer by the user) in the wrong way. Many calll such APIs with a fixed buffersize and do not first retrieve the appropiate buffersize. And they even less check if the returned buffer and returned size is non zero to see if the buffer wasn't too small... ------------------------------------------------------------------------------------------ A total other approach you can take, and much easier for you to program (I think) is to use a VBArray aka SafeArray as return value of your function. Provided C++ knows this kind of data type of course, dunno (but it should though). var vbArray = new VBArray(Interop.Call("your.dll", yourfunc)) var jsArray = vbArray.toArray() |