I keep getting a bad crash when I try to access this dll. It returns a StringBuilder object in Parameter 3 (Results) of ReadRegion but I dont know how to handle it:
C++ Code:
public static extern int ReadRegion(IntPtr hwnd, string name, ref StringBuilder resulst, int offsetX, int offsetY);
Xojo Declare:
Declare Function ReadRegion lib "OpenScrape.dll" (hWND as integer, Region as Cstring, Results as Cstring, offsetX as int32, offsetY as int32) as integer
Dim Result2 as CString
value = ReadRegion(WindowHandle,"p0cardface0rank",Result2, 0,0)
How do I handle the return value datatype of: ref StringBuilder resuls ??
I have tried CString, ptr etc and all fail. Any help would be appreciated.
Also, resultst appears to be a structure of type StringBuilder. You should define the structure in a module and dimension Results as the structure. I suppose that you have the technical documentation describing the structure details.
If the dll you are using is based onthis or this code then you will probably need to do one of the following:
Allocate space in a CString before you make the call then pass in a reference to the CString so its contents can be updated by the dll. i.e.
Dim Result2 As CString = " (256 spaces in here) "
Declare Function ReadRegion lib "OpenScrape.dll" (hWND as integer, Region as Cstring, ByRef Results as CString, offsetX as int32, offsetY as int32) as Int32
value = ReadRegion(WindowHandle,"p0cardface0rank",Result2, 0,0)
Or you could use some code to pad Result2 before the call, its up to you.
Allocate space using a memoryblock and pass that into the dll i.e.
Dim Result2 As New MemoryBlock(256)
Dim p as Ptr = Result2
Declare Function ReadRegion lib "OpenScrape.dll" (hWND as integer, Region as Cstring, Results as Ptr, offsetX as int32, offsetY as int32) as Int32
value = ReadRegion(WindowHandle,"p0cardface0rank",p, 0,0)
system.debuglog(Result2.CString(0))
Dim Result2 As New MemoryBlock(256)
Declare Function ReadRegion lib "OpenScrape.dll" (hWND as integer, Region as Cstring, Results as Ptr, offsetX as int32, offsetY as int32) as Int32
value = ReadRegion(WindowHandle,"p0cardface0rank", Result2, 0,0)
system.debuglog(Result2.CString(0))
Hey thanks for looking at this. I tried every combination of what you suggested and it still crashes. Very frustrating so far. I think Louis is right and I have to do some kind of structure. Of course I have no clue on how to do this…
Looking at the code on the GITHub link provided by @ , I am not so sure that Result should be a structure. A string of some flavour or a memoryblock as suggested by Julian would be the more likely possibilities.
You will find a topic about structures on developer.xojo.com. I like to use structures, even where I could probably use classes instead. I often create structures and then single dimension arrays declared with my structure type, to create internal tables easy to manipulate, sort, etc. An array of classes could probably achieve the same result. It is recommended to use classes, but I have not seen hard facts yet to justify that structures are less efficient or more problematic.
That code on GitHub is probably correct. Somebody compiled the dll for me so it could have been modified a bit but doubtful. I wonder if the window handle is the problem? I noticed that the handles are 6 digits and perhaps this one takes a pointer to the handle? I tried:
Dim WindowHandle as ptr
WindowHandle = ptr(app.WindowHandle)
in which app.WindowHandle = 460238 but that returns all zeros
Window handles are window handles, they could be any number, quite hard to get one of those wrong
Do you have working non-xojo code that uses the dll that I can look at?
I’ve just debugged the dll and its failing inside the first line of ReadRegion, like its not initialised or something. Do you need to load something before calling ReadRegion?
YEUX_V2_API int OpenTablemap(char* filename)
Oh, this is the exposed function by the way:
YEUX_V2_API int ReadRegion(HWND hwnd, char* name, char* &result, int offset)
Where did you get the C++ code in the original post from, the somebody else, did they wrap it up in another layer for you?
Yes you have to load the “table map” file first which works ok:
[code]//load TM
value = OpenTablemap(“IGN9M.tm”)
//Success
if value = 1 then
value = ReadRegion(WindowHandle,“p0cardface0rank”,p, 0,0)
end[/code]
the “p0cardface0rank” is a string located in the table map file which is basically an index that gets the screen scraping coordinates of a particular item:
r$p0cardface0rank 481 63 491 73 ffffffff -50 T3
I was told the “r$” portion of that was not needed when passing the region name to find.
Yeah a friend of mine sent me the dll and how to access it. It might be easier to redo it all and try to compile it myself but I do not know anything about C or even what IDE to use. I hate everything but Xojo
Declare Function ReadRegion Lib "OpenScrape.dll" (hWND As Integer, Region As CString, ByRef Results As Ptr, offsetX As Int32, offsetY As Int32) As Int32
Dim Result2 As New MemoryBlock(256)
Dim p As Ptr = Result2
value = ReadRegion(window1.Handle, name, p, 0, 0)
or this
Declare Function ReadRegion Lib "OpenScrape.dll" (hWND As Integer, Region As CString, ByRef Results As Ptr, offset As Int32) As Int32
Dim Result2 As New MemoryBlock(256)
Dim p As Ptr = Result2
value = ReadRegion(window1.Handle, name, p, 0)
The bottom one works here for me, the string gets through to the dll ok, but if your exported function is as you originally posted the the first one should be ok for you.
Hey Julian. Wow…thanks for this! I will give it a try tonight and let you know how it works. I was getting so frustrated with this so you saved my life…