Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 1, 2020 14:21:16 GMT -5
If I change the majority to ULONG, I actually get it to run, however I now get a subscript out of range error? At the read buffer into string part.
data$ = WINSTRING$(ret)
I'm assuming WINSTRING is a reasonably new command as I haven't come across it before (also it doesn't syntax colour).
And yeah it would be good if the OP could help.
The closest I can get to actually running is;
'Code to work with sockets. Example is a client.
global socketID, bufferID, data$, port
open "http_dll_2_3.dll" for dll as #sk
port = 10002
'First, create a buffer. calldll #sk, "buffer_create", ret as ulong bufferID = ret print bufferID
'Then a socket. calldll #sk, "socket_create", ret as ulong socketID = ret print socketID
'Connect the socket to 127.0.0.1, port 12840 calldll #sk, "socket_connect", socketID as ulong, "127.0.0.1" as double, port as ulong, ret as ulong
while VAL(data$)=0 'Continuously read and display what is sent over the socket, then echo it to the server.
'Read everything the socket has to offer into the buffer
calldll #sk, "socket_read_message", socketID as ulong, bufferID as ulong, ret as ulong
'Read the length of the buffer calldll #sk, "buffer_get_length", bufferID as ulong, ret as ulong length = ret print "length:"; length
'Read the buffer calldll #sk, "buffer_read_string", bufferID as ulong, length as ulong, ret as ulong data$ = winstring$(ret) print "data$"; data$
wend
'We're done so close the socket and buffer calldll #sk, "socket_destroy", socketID as ptr calldll #sk, "buffer_destroy", bufferID as ptr
close #sk
|
|
|
Post by Chris Iverson on Feb 1, 2020 15:44:22 GMT -5
winstring() isn't a new command, and it doesn't have a '$' in it, either. Admittedly, it is confusing because of that, because it does return a string value.
What it does is let LB read a string that's pointed to by the numeric variable passed in to it.
You might get something useful with data$ = winstring(ret).
I need to read all of the documentation though, as this isn't a DLL I've ever used.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 1, 2020 16:45:17 GMT -5
Ah yes, WINSTRING indeed doesn't have a '$', it was in the OP's code snippet and despite reading the helpfile I just read past the command!
Running through the debugger still halts at the buffer_read_string. I've tried all different TYPEs with no avail.
|
|
|
Post by Rod on Feb 2, 2020 8:47:05 GMT -5
What exact error do you get. A memory violation?
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 2, 2020 9:09:02 GMT -5
Liberty just hangs and crashes. I'm running as administrator so it's not a permissions thing. So I don't actually get any error message. It's halts on this line; 'Read the buffer calldll #sk, "buffer_read_string", bufferID as ulong, length as ulong, ret as ptr
Latest version I'm using, as this has changed since the original post.
'Code to work with sockets. Example is a client.
global socketID, bufferID, data$, port
open "http_dll_2_3.dll" for dll as #sk
port = 10002
print "port: ";port
'First, create a buffer.
calldll #sk, "buffer_create", ret as ulong
bufferID = ret
print "buffetID:"; bufferID
'Then a socket.
calldll #sk, "socket_create", ret as ulong
socketID = ret
print "socketID:"; socketID
'Connect the socket to 127.0.0.1, port 12840
calldll #sk, "socket_connect", socketID as ulong, "127.0.0.1" as double, port as ulong, ret as ulong
while 1=1 'Continuously read and display what is sent over the socket, then echo it to the server.
'Clear buffer
calldll #sk, "buffer_clear", bufferID as ulong
print "buffer_clear:"; bufferID
calldll #sk, "socket_update_read", socketID as ulong
print "socket_update_read:"; socketID
'Read everything the socket has to offer into the buffer
calldll #sk, "socket_read_message", socketID as ulong, bufferID as ulong, ret as ulong
print "socket_read_message:"; ret
'Read the length of the buffer
calldll #sk, "buffer_get_length", bufferID as ulong, ret as ulong
length = ret
print "length:"; ret
'Read the buffer
calldll #sk, "buffer_read_string", bufferID as ulong, length as ulong, ret as ptr
print data$ = WINSTRING(ret)
print "data$"; data$
wend
'We're done so close the socket and buffer
calldll #sk, "socket_destroy", socketID as ptr
calldll #sk, "buffer_destroy", bufferID as ptr
close #sk
|
|
|
Post by Rod on Feb 2, 2020 11:44:51 GMT -5
Well your length value is clearly wrong. It’s just filled with the handle of the buffer not the buffer length. So either try using a value you expect if it is fixed length message or concentrate on getting the get buffer length code to work correctly.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 2, 2020 13:24:35 GMT -5
Well it seems the returnType on the CALLDLL makes the difference, setting it to PTR always causes a hang.
This code runs but doesn't receive any UDP traffic.
My code was based on the OP's original, which clearly wasn't tested as they'd used RETURN as a variable.
Until the OP can shed some further light on their DLL, I'm stuck going around in circles.
'Code to work with sockets. Example is a client.
global socketID, bufferID, data$, port, socketStatus, socketCreate
GLOBAL
open "http_dll_2_3.dll" for dll as #sk
port = 10002
print "port: ";port
'buffer_create() : creates new buffer and returns id
calldll #sk, "buffer_create", bufferID as double
print "bufferID: "; bufferID
'buffer_exists(id) : whether a buffer exists
calldll #sk, "buffer_exists", bufferID as double, bufferExist as double
print "bufferExist: ", bufferExist
'udpsocket_create() : Creates a new UDP socket and returns the id.
calldll #sk, "udpsocket_create", socketCreate as double
print "socketCreate: "; socketCreate
'udpsocket_start(id, ipv6, port) : Starts the UDP socket. You have to call this function once before sending or receiving messages.
CALLDLL #sk, "udpsocket_start", socketID as double, FALSE as double, port as double '(id, ipv6, port)
'udpsocket_set_destination(id, address, port) : Sets the destination. It is possible to change the destination as many times as you want.
calldll #sk, "udpsocket_set_destination", socketCreate as double, "127.0.0.1" as double, 10002 as double
'udpsocket_receive(id, buffer_id) : Receives a new message, i.e. copies the contents of the message to the buffer. Returns whether there was a message available.
CALLDLL #sk, "udpsocket_receive", socketID as double, bufferID as double
print "UDP RX - socketID: " ; socketID ;" bufferID: " ; bufferID
WHIlE 1=1
'buffer_read_string(id) : Reads a string from the buffer (NULL-terminated
calldll #sk, "buffer_read_string", bufferID as double, contents as long
data$ = winstring(contents)
print "contents: "; contents ;" data: "; data$
WEND
calldll #sk, "udpsocket_destroy", socketID as double
calldll #sk, "buffer_destroy", bufferID as double
CLOSE #sk
print "CLOSE AND END"
END
|
|
|
Post by Brandon Parker on Feb 2, 2020 22:43:45 GMT -5
Have you tried changing the return type of "buffer_read_string" to ulong? I have always had better success handling strings with ulong data types. I personally use ulong in LB for all handles (i.e. pointers) unless there is something that prevents it. I am not saying that is the issue; I am just curious if you have done so.
{:0)
Brandon Parker
|
|
|
Post by Rod on Feb 3, 2020 6:32:14 GMT -5
Two things. The code was crashing because you were passing an enormous value for the length. So it might have been working but it was choking on the size of the string you were trying to load.
Second, there is a reason Liberty works better with ULong instead of Long. They are both types of exactly the same size but differ in how they are interpreted. The problem Liberty has was clearly explained to me in the past, essentially when the value is passed within Liberty it can be given a negative value, this crashes any API.
If you use Long for any Windows handle and pass or copy the handle within Liberty your code will eventually crash. Look at the handle value with the debugger, you will see it is presented as a negative number. That's why ULong works better it is an unsigned integer and will always remain positive.
Long will work some of the time but not all the time, it depends on the value Windows assigns to the handle.
Some API calls will return negative values so Long is appropriate sometimes but never for Windows handles or pointers.
But we need Ntech to explain what might be happening. and how old his resource was that he created the dll from. Old API code is usually full of old data types that have been superseded.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 3, 2020 15:57:51 GMT -5
I've tried ulong, yes, with the same results. Double seems to produce single numbers when used for socket and buffer ID's. I may have missed something as I don't see a - in front of the number? Unless you mean it's rolled over into a negative number because of the high value? I remember years ago, long had kind of depreciated and the suggestion was to use ulong. It's starting to annoy me now, have been trying this for 4 days! And I have not got a sausage out of it!!!
|
|
|
Post by Chris Iverson on Feb 3, 2020 16:03:51 GMT -5
According to the included documentation, buffer_read_string only has one parameter, not two.
calldll #sk, "buffer_read_string", bufferID as ulong, ret as ulong data$ = winstring(ret)
Try that.
|
|
|
Post by Rod on Feb 4, 2020 6:46:09 GMT -5
Is ipv6 the correct choice? Still away from home but your using an ipv4 IP Not sure if it makes any difference but the docs do say it supports ipv4 And ipv6
|
|
|
Post by Rod on Feb 5, 2020 9:38:20 GMT -5
OK, home and not struggling with an iPhone view of the forum and code. I cant get this to work. I am not even getting past step one. Step one is establishing a buffer. While it opens and I get a sensible "1" as the ID, it wont take any data or string handling and it seems to come back with an error when checking if it exists. Either that or it is returning its own handle. The socket code seems to perform better, at least it does not crash. But neither does it read anything. But that may be the buffer.
nomainwin open "http_dll_2_3.dll" for dll as #sk
port = 10002
'buffer_create() : returns 1 which I take to be the first buffer ID created calldll #sk, "buffer_create", bufferID as ulong
'this is an attempt to fill and read the buffer with string data, all methods fail calldll #sk, "buffer_write_data", bufferID as long , "hello" as ptr, ret as long calldll #sk, "buffer_read_data", bufferID as long, 5 as long, content as ulong if content<>0 then data$ = winstring(content)
"this returns a big number, either its handle or a fail code, hard to tell docs tell me nothing 'buffer_exists(id) : whether a buffer exists calldll #sk, "buffer_exists", bufferID as ulong, ret as long
'udpsocket_create() : returns 1 which I take to be the first udp socket id calldll #sk, "udpsocket_create", socketID as long
'udpsocket_start returns another big number which might be its windows handle docs don't say what the return should be CALLDLL #sk, "udpsocket_start", socketID as long, 0 as long, port as long, ret as long '(id, ipv6, port)
udpsocket_set_destination(id, address, port) returns 1 which I hope is success calldll #sk, "udpsocket_set_destination", socketID as long, "xxx.yyy.1.106" as ptr, port as long, ret as long
"this never fires I am attempting to use UDP Sender/Receiver tool from App Store which appears "to open a port(s) on the given local IP address and sends and receives but not to this code. data$="" while data$="" 'udpsocket_receive(id, buffer_id) calldll #sk, "udpsocket_receive", socketID as long, bufferID as long, ret as long 'buffer_read_string(id) calldll #sk, "buffer_read_string", bufferID as long, content as ulong, ret as long if content<>0 then data$ = winstring(content) wend
calldll #sk, "udpsocket_destroy", socketID as long
calldll #sk, "buffer_destroy", bufferID as long
CLOSE #sk
print "CLOSE AND END"
END
|
|
|
Post by colinmcm on Feb 5, 2020 12:24:55 GMT -5
For what it is worth, I have been trying this also, looking just at the buffer part fo the code provided. I can load into the buffer from a file, and save back to a file, but not programmitically. I cannot print any data in the liberty basic main window whatever I try. See the very untidy code below. This code runs, but is not useful.
I have been looking at the c/c++ source code provided as well as the DLL api listing. Just a thought, but could data from the buffer be being sent directly to stdout, which liberty basic cannot capture directly? Would that be possible? I cannot see anywhere in the code samples provided a hook into stdout, but it all might work in a full application.
Colin McMurchie
'Code to work with sockets. Example is a client.
open "http_dll_2_3.dll" for dll as #sk
'buffer_create() : creates new buffer and returns id calldll #sk, "buffer_create", bufferID as double buffer1 = bufferID print "buffer1 is: "; buffer1
'=============== create another buffer ==============
'buffer_create() : creates new buffer and returns id calldll #sk, "buffer_create", bufferID as double buffer2 = bufferID print "buffer2 is: "; buffer2
'================ try to read and write to/from a file +++ working +++++++++++++++++ file$ = "index.php" ' buffer_read_from_file(buffeID, filename) ' calldll #sk, "buffer_read_from_file", buffer1 as double, file$ as ptr, result as ulong ' print "read from file"
' buffer_read_append_to_file(bufferID, filename) ' calldll #sk, "buffer_append_to_file", buffer1 as double, result as ulong
print "can add to file" '================================================================ '============ now to add to a buffer '================ now to try appending to a file ================== calldll #sk, "buffer_write_to_file", buffer1 as double, file$ as ptr, result as ulong 'now try to read data ' first try to find where we are in buffer ' buffer_get_pos(id) : returns current reading position ' calldll #sk, "buffer_get_pos", buffer1 as double, result as ulong ' postion = result ' print "position in buffer is "; position for x = 1 to 5 calldll #sk, "buffer_read_string", bufferID as double, contents as ulong print x ; "data is"; winstring( contents) next x '=============== try a loop ===================
' calldll #sk, "udpsocket_destroy", socketID as double calldll #sk, "buffer_destroy", buffer1 as double calldll #sk, "buffer_destroy", buffer2 as double
CLOSE #sk
print "CLOSE AND END"
END
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 5, 2020 14:17:00 GMT -5
Still not working (produces nothing). But it does run.
But I think the calls made to the DLL are returning values when it should be setting values. So it looks like the documentation is incorrect or at least the way LB interacts with the DLL.
The code below runs, however if you step thru in the debugger, it changes the bufferID, socketID etc when it should be passing values not setting them.
If you change the double into ulong on the buffer/socketID it returns a large number and crashes/hangs.
I've also tried using my local ip address rather than the loopback ip address, when trying this in java (built in calls, not this DLL) it wouldn't receive using the loopback only the machines ip address.
global socketID, bufferID, data$, port, socketStatus, socketID, bufferExist
open "http_dll_2_3.dll" for dll as #sk
port = 10002
print "port: ";port
'buffer_create() : creates new buffer and returns id
calldll #sk, "buffer_create", bufferID as double
print "bufferID: "; bufferID
'buffer_exists(id) : whether a buffer exists
calldll #sk, "buffer_exists", bufferID as double, bufferExist as ulong
print "bufferExist: ", bufferExist
'udpsocket_create() : Creates a new UDP socket and returns the id.
calldll #sk, "udpsocket_create", socketID as double
print "socketCreate: "; socketID
'udpsocket_start(id, ipv6, port) : Starts the UDP socket. You have to call this function once before sending or receiving messages.
CALLDLL #sk, "udpsocket_start", socketID as double, FALSE as double, port as ulong '(id, ipv6, port)
'udpsocket_set_destination(id, address, port) : Sets the destination. It is possible to change the destination as many times as you want.
calldll #sk, "udpsocket_set_destination", socketID as double, "192.168.0.37" as ptr, port as ulong
'At this call above, port changes to a random number, so this is returning something rather than setting the port
'udpsocket_receive(id, buffer_id) : Receives a new message, i.e. copies the contents of the message to the buffer. Returns whether there was a message available.
CALLDLL #sk, "udpsocket_receive", socketID as double, bufferID as double
print "UDP RX - socketID: " ; socketID ;" bufferID: " ; bufferID
WHIlE 1=1
'Clear buffer
calldll #sk, "buffer_clear", bufferID as ulong
'print "buffer_clear:"; bufferID
calldll #sk, "socket_update_read", socketID as ulong
'print "socket_update_read:"; socketID
calldll #sk, "buffer_read_string", bufferID as ulong, ret as ulong
data$ = winstring(ret)
IF data$ <> "" THEN print "data$:" + data$
'buffer_read_hex(id, len) : Reads a number of bytes from the buffer and converts the result to a hexadecimal string.
calldll #sk, "buffer_read_hex", socketID as ulong, ret as ulong
data$ = winstring(ret)
IF data$ <> "" THEN print "data$ (HEX):" + data$
WEND
calldll #sk, "udpsocket_destroy", socketID as double
calldll #sk, "buffer_destroy", bufferID as double
CLOSE #sk
print "CLOSE AND END"
END
|
|