LPSTR to PBYTE

L

Larry

Hi, I have a problem with the following code:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

typedef char* STRING;
BOOL saluto(PBYTE);

int main()
{

PBYTE marameo = new BYTE[10];
saluto(marameo);

printf("%s\n", marameo);

system("pause");
return 0;
}

BOOL saluto(PBYTE a)
{
STRING kk = "Hello World!";
a = (PBYTE)kk;
return true;
}

basically I call the function saluto() to change the content of /marameo/
but nothing happens....why? thanks
 
R

red floyd

Hi, I have a problem with the following code:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

typedef char* STRING;
BOOL saluto(PBYTE);

int main()
{

PBYTE marameo = new BYTE[10];
saluto(marameo);

printf("%s\n", marameo);

system("pause");
return 0;
}

BOOL saluto(PBYTE a)
{
STRING kk = "Hello World!";
a = (PBYTE)kk;
return true;
}

basically I call the function saluto() to change the content of
/marameo/ but nothing happens....why? thanks

Because you changed a *COPY* of marameo to point somewhere else.
You didn't change the data stored in marameo.

BTW, your code is C, not C++. Also, as Ian noted, PBYTE is a
windows-ism.
 
L

Larry

red floyd said:
On 1/11/2010 4:49 PM, Larry wrote:
Because you changed a *COPY* of marameo to point somewhere else.
You didn't change the data stored in marameo.

BTW, your code is C, not C++. Also, as Ian noted, PBYTE is a
windows-ism.

what do you mean by windows-ism? supposed I needed them elsewhere wouldn't
be correct to do something like this?:

typedef unsigned char BYTE;
typedef BYTE *PBYTE;

int main() {
PBYTE marameo = BYTE[10];
}

// it is still pure C++ I think...(i just need a pointer to a unsigned
char!)

anyway, I sorted out like this:

#include <string.h>
#include <stdio.h>

typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef char *STRING; // Ok, this may suck at a first glance!

BOOL marameo(PBYTE);

int main()
{
PBYTE pbMyVar = BYTE[15];
if(marameo(pbMyVar))
{
printf("%s\n", pbMyVar);
}
return 0;
}

BOOL marameo(PBYTE pbVar)
{
STRING szVar = "Hello World!";
memcpy(pbVar, szVar, 15);
return true;
}

thanks
 
G

Gert-Jan de Vos

red floyd said:
On 1/11/2010 4:49 PM, Larry wrote:
Because you changed a *COPY* of marameo to point somewhere else.
You didn't change the data stored in marameo.
BTW, your code is C, not C++.  Also, as Ian noted, PBYTE is a
windows-ism.

what do you mean by windows-ism? supposed I needed them elsewhere wouldn't
be correct to do something like this?:

typedef unsigned char BYTE;
typedef BYTE *PBYTE;

int main() {
 PBYTE marameo = BYTE[10];

}

// it is still pure C++ I think...(i just need a pointer to a unsigned
char!)

anyway, I sorted out like this:

#include <string.h>
#include <stdio.h>

typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef char *STRING; // Ok, this may suck at a first glance!

BOOL marameo(PBYTE);

int main()
{
 PBYTE pbMyVar = BYTE[15];
 if(marameo(pbMyVar))
 {
  printf("%s\n", pbMyVar);
 }
 return 0;

}

BOOL marameo(PBYTE pbVar)
{
 STRING szVar = "Hello World!";
 memcpy(pbVar, szVar, 15);
 return true;

}

A more idiomatic C++ version of this would be like:

#include <iostream>
#include <string>

std:string marameo()
{
return "Hello World!";
}

int main()
{
std::string myVar = marameo(pbMyVar);
if (!myVar.empty())
{
std::cout << myVar << std::endl;
}
}

No need for PBYTEs, new or memcpy.
 
M

Michael Doubez

red floyd said:
On 1/11/2010 4:49 PM, Larry wrote:
Because you changed a *COPY* of marameo to point somewhere else.
You didn't change the data stored in marameo.
BTW, your code is C, not C++.  Also, as Ian noted, PBYTE is a
windows-ism.

what do you mean by windows-ism? supposed I needed them elsewhere wouldn't
be correct to do something like this?:

typedef unsigned char BYTE;
typedef BYTE *PBYTE;

int main() {
 PBYTE marameo = BYTE[10];

}

// it is still pure C++ I think...(i just need a pointer to a unsigned
char!)

anyway, I sorted out like this:

#include <string.h>
#include <stdio.h>

typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef char *STRING; // Ok, this may suck at a first glance!

Even on second glance because
const STRING str;

is not a pointer to constant string data but a constant pointer to
string data.
BOOL marameo(PBYTE);

This should be:
bool marameo(PBYTE);
int main()
{
 PBYTE pbMyVar = BYTE[15];

Does this actually compile ?
A table is declared as:
BYTE pbMyVar[15];
 if(marameo(pbMyVar))
 {
  printf("%s\n", pbMyVar);

I am not sure but recent compilers could issue a warning here: %s
expects a char* not an unsigned char*.
 }
 return 0;

}

BOOL marameo(PBYTE pbVar)
{
 STRING szVar = "Hello World!";
 memcpy(pbVar, szVar, 15);

szVar is only 13 bytes long. Using memcpy like that, you are accessing
uninitialised data or even data in protected area.

Prefer the following form:
char szVar[] = "Hello World!";
memcpy(pbVar, szVar, sizeof(szVar) );
 return true;

main() doesn't return a boolean but a int. With true, I guess the
program will return a value different from 0 which is usually an error
from the system point of view.

Use:
return EXIT_SUCCESS;
 
J

James Kanze

Code and group, try a windows programming group!

Except that once you get past the stupid typedef's (PBYTE,
etc.), the problem he has has nothing to do with Windows, and
everything to do with C++. (And for starters, he should get rid
of the stupid typedef's, so we can see what is going on.)
 
J

James Kanze

"red floyd" <[email protected]> ha scritto nel
messaggionews:[email protected]...
what do you mean by windows-ism?

That it was an idea that permeated the Windows interface for
awhile, before everyone realized how stupid it was.
supposed I needed them elsewhere wouldn't be correct to do
something like this?:
typedef unsigned char BYTE;
typedef BYTE *PBYTE;

From a language standpoint, it's legal. But it ranks as
obfuscation: something done to make your code intentionally
difficult to read and to maintain.
int main() {
PBYTE marameo = BYTE[10];

// it is still pure C++ I think...(i just need a pointer to a unsigned
char!)

If you need a pointer to an unsigned char: "unsigned char*".
 
L

Larry

From a language standpoint, it's legal. But it ranks as
obfuscation: something done to make your code intentionally
difficult to read and to maintain.
If you need a pointer to an unsigned char: "unsigned char*".

think I own you a wider explanation on what I am dealing with. I'm writing a
class to wrap up the waveForm API, especially the waveInxxx functions for
the moment.

The API provides me with the WAVEHDR structure. This structure defines the
header used to identify a waveform-audio buffer.

typedef struct {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
struct wavehdr_tag* lpNext;
DWORD reserved;
} WAVEHDR;

where (LPSTR)lpData is a: Long pointer to the address of the waveform
buffer.

Also, very important to me are: dwBufferLength and dwBytesRecorded.

Before starting capturing from the audio device I set up some buffers:

// Define WAVEHDR Structure:
//
// 3 buffers, 4096 bytes long each:
//
// DWORD dwNumBuffers = 3;
// DWORD dwBufferLength = 4096;

WAVEHDR *buff = new WAVEHDR[dwNumBuffers];
for (int i = 0; i<(int)dwNumBuffers; i++)
{
ZeroMemory(&buff, sizeof(buff));

buff.lpData = (LPSTR) malloc(dwBufferLength);
buff.dwBufferLength = dwBufferLength;
buff.dwBytesRecorded = 0;
buff.dwUser = 0;
buff.dwFlags = 0;
buff.dwLoops = 0;

// ... pass the buffer to the system ...
}

As far as my function is concerned, it basically reads the data from the
buffer and returns the bytes recorded:

(...)
PBYTE pWAVBuffer = new BYTE[dwBufferLength];
DWORD bytesrec = getBuffer(pWAVBuffer);
(...)
delete[] pWAVBuffer;

DWORD getBuffer(PBYTE pWAVBuffer)
{
// ... (some code to deal with the CALLBACK) ...

if(buff[k].dwFlags & WHDR_DONE)
{
memcpy(pWAVBuffer, buff[k].lpData, buff[k].dwBytesRecorded);
}

// ... (some more code to deal with something else) ...

return buff[k].dwBytesRecorded;
}

As you can see I'm using memcpy to copy from LPSTR to PBYTE using the
correct amount of bytes...

Do you think I am in the right direction with that?
 
L

Larry

Except that once you get past the stupid typedef's (PBYTE,
etc.), the problem he has has nothing to do with Windows, and
everything to do with C++. (And for starters, he should get rid
of the stupid typedef's, so we can see what is going on.)

Ok, followed your advice. Do you think the following is more C++ like?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool saluto(unsigned char*);
const int len = 15;

int main()
{
unsigned char* szString = new unsigned char[len];
saluto(szString);

printf("%s\n", szString);

delete[] szString;

system("pause");
return EXIT_SUCCESS;
}

bool saluto(unsigned char* szString)
{
char _szTempString[] = "Hello World!";
memcpy(szString, _szTempString, len);
return true;
}

thanks
 
L

Larry

It is C++, not C.
PBYTE marameo = new BYTE[10];

given those:

"An unsigned char is a (unsigned) byte value (0 to 255). You may be thinking
of "char" in terms of being a "character" but it is really a numerical
value. The regular "char" is signed, so you have 128 values, and these
values map to characters using ASCII encoding. But in either case, what you
are storing in memory is a byte value."

"unsigned char is simply a BYTE. An unsigned integer of (usually) 8 bits."

Do you think is that bad if I define my onw type to deal with binary string?
(8-bit based)

unsigned char byte;

byte var[] = (...binary value...)

// or:

unsigned char* byte;

byte var = (...binary value...)

I don't need to operate on those binary strings, I just need to both read
them and write them...

thanks
 
M

Michael Doubez

think I own you a wider explanation on what I am dealing with. I'm writing a
class to wrap up the waveForm API, especially the waveInxxx functions for
the moment.

The API provides me with the WAVEHDR structure. This structure defines the
header used to identify a waveform-audio buffer.

typedef struct {
 LPSTR lpData;
 DWORD dwBufferLength;
 DWORD dwBytesRecorded;
 DWORD dwUser;
 DWORD dwFlags;
 DWORD dwLoops;
 struct wavehdr_tag* lpNext;
 DWORD reserved;

} WAVEHDR;

This is C syntax.
Prefer:

struct WAVEHDR {
// ...
};
where (LPSTR)lpData is a: Long pointer to the address of the waveform
buffer.

I have not seen long pointer since windows 3.1. Are you really going
to code for that plateform ?

DWORD is basically a unsigned int; the only advantage is that it is
guaranteed to be 32 bits on 64 bit architecture. I expect it is not
what you want here.
Also, very important to me are: dwBufferLength and dwBytesRecorded.

Before starting capturing from the audio device I set up some buffers:

// Define WAVEHDR Structure:
//
// 3 buffers, 4096 bytes long each:
//
// DWORD dwNumBuffers  = 3;
// DWORD dwBufferLength = 4096;

WAVEHDR *buff = new WAVEHDR[dwNumBuffers];
for (int i = 0; i<(int)dwNumBuffers; i++)
{

This initialisation should go in the constructor
WAVEHDR:WAVEHDR()
: lpData()
, dwBufferLength()
, dwBytesRecorded()
, dwUser()
, dwFlags()
, dwLoops()
, lpNext()
, reserved()
{
}
 ZeroMemory(&buff, sizeof(buff));

 buff.lpData          = (LPSTR) malloc(dwBufferLength);
 buff.dwBufferLength  = dwBufferLength;
 buff.dwBytesRecorded = 0;
 buff.dwUser          = 0;
 buff.dwFlags         = 0;
 buff.dwLoops         = 0;

// ... pass the buffer to the system ...

}

As far as my function is concerned, it basically reads the data from the
buffer and returns the bytes recorded:

(...)
PBYTE pWAVBuffer = new BYTE[dwBufferLength];
DWORD bytesrec = getBuffer(pWAVBuffer);
(...)
delete[] pWAVBuffer;


This code is not exception safe.
DWORD getBuffer(PBYTE pWAVBuffer)

Why not call it read ? It is what you are actually doing.
{
 // ... (some code to deal with the CALLBACK) ...

 if(buff[k].dwFlags & WHDR_DONE)
 {
  memcpy(pWAVBuffer, buff[k].lpData, buff[k].dwBytesRecorded);
 }

 // ... (some more code to deal with something else) ...

 return buff[k].dwBytesRecorded;

}

As you can see I'm using memcpy to copy from LPSTR to PBYTE using the
correct amount of bytes...

Do you think I am in the right direction with that?

With using memcpy() to copy data yes. And copying to unsigned char is
guaranteed to preserve the binary layout.

Now, IMO the P* naming for pointers is still obfuscation.
 
L

Larry

I have not seen long pointer since windows 3.1. Are you really going
to code for that plateform ?

This is the API I'm dealing with:
http://msdn.microsoft.com/en-us/library/aa909814.aspx
DWORD is basically a unsigned int; the only advantage is that it is
guaranteed to be 32 bits on 64 bit architecture. I expect it is not
what you want here.

the same above.
This initialisation should go in the constructor
WAVEHDR:WAVEHDR()
: lpData()
, dwBufferLength()
, dwBytesRecorded()
, dwUser()
, dwFlags()
, dwLoops()
, lpNext()
, reserved()
{ }

I get this struct from windows, I don't think I can init it in place of. (I
hope this is done internally by the API)
Now, IMO the P* naming for pointers is still obfuscation.

I am going to change that. After all, if the audio is in the /char*/ format,
why should I change it to /unsigned char*/ ??
 
J

James Kanze

"James Kanze" <[email protected]> ha scritto nel
messaggionews:a99c74c5-d80c-43b5-a2a4-f174ba0bc7af@u41g2000yqe.googlegroups.com...
Ok, followed your advice. Do you think the following is more C++ like?

More or less:). (C++ means different things to different
people.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

For example, I'd use

#include <iostream>
#include <string>

here.
bool saluto(unsigned char*);
const int len = 15;
int main()
{
unsigned char* szString = new unsigned char[len];
saluto(szString);
printf("%s\n", szString);
delete[] szString;
system("pause");
return EXIT_SUCCESS;
}
bool saluto(unsigned char* szString)
{
char _szTempString[] = "Hello World!";
memcpy(szString, _szTempString, len);

And of course, this is undefined behavior, since you're copying
more bytes than you have.

In C++, I'd be using std::string or std::vector---the latter if
I really needed unsigned char for text (or a special
instantiation of std::basic_string, if you're really expert, and
need it). In practice, however, for any number of reasons,
unsigned char doesn't work for text. You're better off using
char, and remembering to cast when you need for the value to be
between 0 and UCHAR_MAX.

Anyway, my version of saluto (supposing unsigned char was really
needed) would be:

void
saluto( std::vector< unsigned char >& results)
{
static char const value[] = "Hello World!";
results.insert(results.end(), value, value + sizeof(value));
}

Also, most experienced programmers would forgo the funny
prefixes. Another Microsoft experiment that failed.
 
J

James Kanze

This is C syntax.

It's probably a C interface. Most API are defined in terms of
C.
struct WAVEHDR {
// ...
};

Except don't define a symbol all caps (unless it's a macro).

His struct looks like the sort of thing Microsoft developed some
years back. And are now locked into. In my own code, I'd use
"struct WaveHeader", rather than the typedef, there'd be no
DWORD or LPSTR, and none of the Hungarian prefixes. If you're
interfacing to an existing interface, however... None of my
local variables would have the prefixes, but the name WAVEHDR is
pretty much imposed, and I've got a couple of DWORD as well
where I interface with Windows. (It's easier to just write
DWORD that it is to figure out what the actual type is.)
I have not seen long pointer since windows 3.1. Are you really
going to code for that plateform ?

Modern Microsoft may not have long pointers, but it still has
LPSTR.
DWORD is basically a unsigned int; the only advantage is that
it is guaranteed to be 32 bits on 64 bit architecture. I
expect it is not what you want here.

DWORD is guaranteed to be the type the interface uses in its
structure.

[...]
With using memcpy() to copy data yes. And copying to unsigned
char is guaranteed to preserve the binary layout.

And memcpy is guaranteed to copy "as if" through pointers to
unsigned char. (It takes void* as arguments, so you can pass it
a pointer to anything.)
Now, IMO the P* naming for pointers is still obfuscation.

Mine too, but some of the names may be imposed by the interface.
 
D

Dilip

DWORD is guaranteed to be the type the interface uses in its
structure.

DWORD has always confused me a little bit. Like Michael I always
remembered DWORD to be a typedef for unsigned int and will remain 32
bits even on a 64 bit arch. Why then do we have a DWORD32 datatype?
There is even a DWORD64 datatype but that at least makes sense.

DWORD: http://msdn.microsoft.com/en-us/library/cc230318(PROT.10).aspx
DWORD32: http://msdn.microsoft.com/en-us/library/cc230319(PROT.10).aspx
DWORD64: http://msdn.microsoft.com/en-us/library/cc230320(PROT.10).aspx
 
I

Ian Collins

Dilip said:
DWORD has always confused me a little bit. Like Michael I always
remembered DWORD to be a typedef for unsigned int and will remain 32
bits even on a 64 bit arch. Why then do we have a DWORD32 datatype?
There is even a DWORD64 datatype but that at least makes sense.

I'm not sure who we is.

The most portable solution when a fixed width type is required (which
isn't that often) is the standard C int[8|16|32|64]_t types.
 
Ö

Öö Tiib

I'm not sure who we is.

The 'we' is probably people using Windows API for writing software. It
is widely used operating system and so there is numerous user base and
so there is a large market for software solutions.
The most portable solution when a fixed width type is required (which
isn't that often) is the standard C int[8|16|32|64]_t types.


It is most portable way of defining interface. When you are using
others legacy interface (on current case it is MS API) then best is to
stick with terms it defines. MS compilers come without stdint.h so one
has to provide a copy or use boost/stdint.hpp.
 
Ö

Öö Tiib

As you can see I'm using memcpy to copy from LPSTR to PBYTE using the
correct amount of bytes...

Do you think I am in the right direction with that?

Probably with correct conversions. LPSTR is char* and PBYTE is
unsigned char* and both are used as abstraction of 'array of bytes'.
What you do wrong is that you use both new and malloc in same code. It
indicates that you are unsure if you want to write it in C or C++.
Choose one or other, otherwise it is a mess.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top