Hello.

Recently I started working with data transfer channels, well, those that are NamedPipe.

The functions of writing and reading into the channel, if we consider the very basis, look like this:

WriteFile(HANDLE hFile, LPVOID lpBuffer, ... ); ReadFile(HANDLE hFile, LPVOID lpBuffer, ... ); 

With the first parameter, everything is clear, this is the channel to which we are writing, but here is the second. The second parameter of type LPVOID judging from the description in Windows Data Types is a pointer to any type.

However, it is impossible to write anything to the channel except char (as well as reading), the compiler says that it cannot convert, say, int to LPVOID .

The question is how to work with LPVOID ? Maybe it is necessary to translate the int into it or something else? And why then the compiler does not swear to char ? (Only if this cahr declared like this: char *X = new char[const]; )

Another question: You can write to the stream of any type. How to read from a stream to a variable of any type? Nothing happens, only in char it is possible, which is declared via new char (the compiler skips, but when reading, error 998 Invalid access to memory location occurs.)

  • 2
    Well, the compiler can be slapped over the ears, if necessary. But. There must be an address. Accordingly, it is necessary to convert to LPVOID not int, but int *. - alexlz
  • Thanks) I 'll try) - BlackOverlord
  • @BlackOverlord thanks for the link is very useful. - ProkletyiPirat
  • > Another question: You can write to the stream of any type. How to read from a stream to a variable of any type? Nothing happens, only in char it is possible, which is declared via new char (the compiler skips, but error 998 Invalid access to memory location occurs when reading.) A specific example plz - gecube

2 answers 2

In general, it is clear that LPVOID is a pointer. At the same time, this is a pointer (P from P ointer) to anything (VOID), and even far (L from L ong). Those. It turns out such a thing:

 typedef void far *LPVOID; 

But, first, I am not sure that in Windows the far specifier is now relevant, since used flat memory model. In earlier versions of compilers and OS, this was probably important. I remember the torment with Borland 3.1, in which the memory model played a very large role. Secondly, it is wrong to cast its pointers to a type other than LPVOID when calling the specified system functions. The fact is that in the next versions of the OS and development tools can override this type and then cranks. Therefore, to do the following:

 int *blablabla; // наш указатель LPVOID lpData; lpData = (LPVOID)blablabla; // или правильнее lpData = static_cast<LPVOID>(blablabla); 

Well, and further already we transfer the lpData pointer to f-tion

  • 3
    Well, the lpData variable itself is hardly needed. Enough WriteFile (..., (LPVOID) blablabla, ...) - avp
  • Yeah. In vs there is a typedef void * LPVOID; typedef void far * LPVOID; available that with far. Although I was pretty sure that this is an ordinary void. Himself far is just #define far - manking
  • one
    @gecube, if you need a variable for something else, then of course you need to do it. - By the way, what exactly is static_cast better? Can you clearly explain? I certainly read more than once about this, but apparently I don’t get into why in real programs it is (static_cast), so I constantly forget the explanations. - avp
  • five
    Well, besides the fact that static_cast looks ugly and longer, it has an advantage. With style cast, it works in such a way that it first tries to make static_cast , then reinterpret_cast . If necessary, it can do const_cast . Those. it turns out that the record is more concise, but the conversion is unsafe. And inexperienced users often thoughtlessly use the c-style cast to shut down warnings and compiler errors. Here is a sample code: ideone.com/Eu7a4l And that we have not yet reached the pointers to classes. - gecube
  • 2
    Well yes. Also, as they say, brackets are easier to track, it is more clear to which value the cast is applied. Well, the length is also useful. The less cast'ov - the better. - alexlz

Is this kind of ordinary void *?

 // создаем переменную на которую будет ссылаться наш указатель int var = 5; std::cout << "\nvar=" << (int)var; // создаем указатель на неопределенный тип void * pointer; pointer = &var; // помещаем в указатель адрес переменной var // теперь приводим указатель к типу int и выполняем доступ по значеннию std::cout << "\nуказатель=" << *(int*)pointer; 

As a result, we should get a conclusion of 5

 // приводим указатель void * pointer к указателю int * int * pointer_int = (int*)pointer; // осуществляем разыменование указателя int *. То есть // выполняем доступ по значению int var2 = *pointer_int; std::cout << "\nvar2=" << var2; // Таким образом всё это выглядит так: // pointer -> (int*)pointer привели к требуемому -> *(int*)pointer разыменовали приведенный к типу указатель. 
  • one
    not quite normal void. See my answer. - gecube