• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

web navigation O2

Started by Eduardo Jorge, June 28, 2019, 06:48:22 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

No, they aren't another name for integer pointers. They're variants passed by value.

Charles Pegge

They are 16 byte structures (24 bytes in x64) so its strange to see them loaded straight onto the stack. UDTs are rarely passed directly.

José Roca

#17
In the beginning of COM programming, variants and guids (both 16-byte structures) were always passed by reference. Later, they decided that it was more convenient to pass them by value. Variants and guids can also be returned as the result of a method, although different languages do it well... differently, because it's never too late to create incompatibilities. I think that Microsoft C++ compilers return them in the stack. Delphi and GCC, I don't know.

So you can find old rechnologies, like the Dictionary Object, whose methods are byref variants (guess that it was because VB Script was not able to deal by byval variants at that time), and more recent technologies and the .Net Framework, that, in general, only uses byref variants and guids for out parameters and byval for in parameters.


Charles Pegge

It gets messy with MS64.

Variants inflate to 24 bytes due to their non-optimal structure, which gets padded out according to the standard C type-alignment rules.

Then the MS64 calling convention requires the 1st 4 (non-float) params to be passed in RCX,RDX,R8,R9 (8 bytes each). The remainder of the params must be stored within a stack frame before making the call.

The base of the stack frame (value in RSP) must be kept 16-byte aligned.

So we have to struggle with some very poor design decisions in the system.


Zlatko Vid

Jose
I don't want to argue with you because you have lot more experience than me in such a things
BUT
i was not completely in wrong
from wiki-diki
In Visual Basic (and Visual Basic for Applications) the Variant data type is a tagged union 

so ...if is union then is UDT, if is UDT then is some sort of pointer
so .. if i understand it each time we create variant we also create some sort of union structure.

again ...i am not very smart in that stuff ..so i just follow the logic.   ;D
i think ..

all best ...Aurel

José Roca

An UDT is not a pointer, but a composite data type. A Variant is an structure which has a member that is an Union.

When the parameter is byref variant, you pass a pointer to that structure, but when it is byval, you have to push all the members of that structure into the stack. As Charles has pointed, it is not difficult to do with 32 bit, but it is messy with 64-bit.

Besides, the methods get_responseBody and get_responseStream return a Variant as the result, not a pointer to a Variant.

Charles Pegge

#21
I see this is how variants are returned in C/C++

The first param (after the invisible this) is a variant reference. The caller must create a variant to receive the return value.

I have already adopted a similar scheme for all direct UDT returns, with invisible returns variables..

Quote
Visual Basic Syntax

strValue = oServerXMLHTTPRequest.responseBody 

C/C++ Syntax

HRESULT get_responseBody(VARIANT* pvarVal); 

https://msdn.microsoft.com/en-us/windows/ms753682(v=vs.71)

José Roca

> The first param (after the invisible this) is a variant reference. The caller must create a variant to receive the return value.

This applies when using low-level COM, that almost always returns an HRESULT value as the result of a method, but not when using automation languages. Anyway, O2 does not support COM Automation, so O2 users must learn that they can't use something like bstrString=pIXMLHTTPRequest->responseText;

Zlatko Vid

QuoteWhen the parameter is byref variant, you pass a pointer to that structure, but when it is byval, you have to push all the members of that structure into the stack. As Charles has pointed, it is not difficult to do with 32 bit, but it is messy with 64-bit.

Hi Jose

Thank you , i hope that i understand it now..

Eduardo Jorge

if I understand, it is not possible to use with O2
So is there an interface for getting files, or reading, working the html of a web page?

Charles Pegge

#25
There is an o2 folder: examples\system\winsock containing 2 examples of low-level internet access.

Eduardo Jorge

thank you Charles
I looked at Dict_Send_Receive.o2bas but it seems to be very advanced for me

Charles Pegge

I found Wininet to be be quite friendly. This is how to get a web page, and file it:


extern lib "wininet.dll"

! InternetOpenA
! InternetOpenUrlA
! InternetCloseHandle
! InternetReadFile

end extern

string buf=nuls 100000
string url="https://www.oxygenbasic.org/index.html"
int cbytes
sys hInternet
sys hFile
hInternet = InternetOpenA( "o2demo",0,0,0,0 )
hFile = InternetOpenUrlA( hInternet,url,0,0,0,0 )
InternetReadFile( hFile,buf,len(buf),@cbytes )
InternetCloseHandle( hFile )
InternetCloseHandle( hInternet )
print left( buf,500 )
putfile( "t.txt",left(buf,cbytes) )



NOTES:
======

'https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetopena
'https://docs.microsoft.com/en-us/cpp/mfc/wininet-basics?view=vs-2019#_core_create_a_very_simple_browser


/*
% INTERNET_OPEN_TYPE_DIRECT 1
% INTERNET_FLAG_ASYNC 0x10000000
*/

/*
extern lib "wininet.dll"

sys InternetOpenA(
  LPCSTR lpszAgent,
  DWORD  dwAccessType,
  LPCSTR lpszProxy,
  LPCSTR lpszProxyBypass,
  DWORD  dwFlags
);

BOOLAPI InternetCloseHandle(
  HINTERNET hInternet
);

BOOLAPI InternetCanonicalizeUrlA(
  LPCSTR  lpszUrl,
  LPSTR   lpszBuffer,
  LPDWORD lpdwBufferLength,
  DWORD   dwFlags
);
sys InternetOpenUrlA(
  HINTERNET hInternet,
  LPCSTR    lpszUrl,
  LPCSTR    lpszHeaders,
  DWORD     dwHeadersLength,
  DWORD     dwFlags,
  DWORD_PTR dwContext
);

BOOLAPI InternetReadFile(
  HINTERNET hFile,
  LPVOID    lpBuffer,
  DWORD     dwNumberOfBytesToRead,
  LPDWORD   lpdwNumberOfBytesRead
);

BOOLAPI InternetFindNextFileA(
  HINTERNET hFind,
  LPVOID    lpvFindData
);

*/

'#include <afxinet.h>

/*
void DisplayPage(LPCTSTR pszURL)
{
   CInternetSession session(_T("My Session"));
   CStdioFile* pFile = NULL;
   CHAR szBuff[1024];
   //use a URL and print a Web page to the console
   pFile = session.OpenURL(pszURL);
   while (pFile->Read(szBuff, 1024) > 0)
   {
      printf_s("%1023s", szBuff);
   }
   delete pFile;
   session.Close();
}
*/

Eduardo Jorge

Thank you, Charles.
is basically what I need, I just do not understand why it does not grab all the content.
for most Json I'm going to use is 100% because they are small but some are of indefinite size
I tested this
http://data.ny.gov/resource/d6yy-54nr.json
and does not take all content

José Roca

> is basically what I need, I just do not understand why it does not grab all the content.

This is because the buffer is too small.