how convert a 2D vector to void*?

how can i convert 2D vector to void*?
creating a 2D vector:
std::vector<std::vector<unsigned int>> PixelColors( ConsoleHeight , std::vector<unsigned int> (ConsoleWidth, 0));
(vector type 2 times)
heres how i try conver it to void*:
static_cast<void*>(PixelColors.data())
but these is wrong... so how can convert 2D vector to void*?
i did:
1
2
3
4
5
6
7
8
9
std::vector<std::vector<unsigned int>> PixelColors( ConsoleHeight , std::vector<unsigned int> (ConsoleWidth, 0));
 unsigned int VoidPixels[ConsoleHeight*ConsoleWidth];
        for(int y=0; y<ConsoleHeight; y++)
        {
            for(int x=0; x<ConsoleWidth; x++)
            {
                VoidPixels[y*ConsoleWidth+x]=PixelColors[y][x];
            }
        }

but is there a more simple method?
yes.. works fine
each vector has its own buffer. you can't use a 1-d pointer to represent it properly; all you get is a void pointer of vectors, which is about useless.

void * specifically should be avoided more often than not. Its likely that you are doing something weird / incorrect.

punching a void* into a function is just address of:
foo(&something); //&something is a strongly typed pointer, but if foo accepts a void* parameter, it will work, you don't have to cast it. If however foo uses the pointer, it needs to be *exactly* what the function is expecting.

Old MFC does not use vectors. Microsoft didn't invent them, therefore they don't exist :P
seriously they just never updated the code base to use modern concepts, so its more C like than most things you would deal with today.

just pass in pixelcolors directly. nothing more. no & or anything. its a void pointer. you don't need this extra copy that you then get all medieval on, just use the C array since that is what it wants.
Last edited on
i use void*.. because the StretchDIBits() use it on tenth parameter.
I understand that. But YOU don't need to cast it to void * or use one directly, you just pass along a typed pointer. Its when YOU start typing "void*" in your code that you should stop and think whether that is a good idea or not.
Last edited on
This function: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-stretchdibits

A C function that takes 1D array of bytes, size(s) of the array, and description of datatype that the array contains, etc?

Btw, that is const void*.

If the function expects 1D array, then give it 1D array.

The unsigned int VoidPixels[ConsoleHeight*ConsoleWidth]; remains an error in standard C++, because it is VLA.

Dynamically allocated 1D array with every uint element initialized to 0:
std::vector<unsigned int> VoidPixels( ConsoleHeight*ConsoleWidth, 0 );
i can't use directly the 'PixelColors.data()' on void* parameter
Is it because you did not cast the pointer, or because the PixelColors is vector of vectors -- not 1D?
but is there a more simple method?
yes.. works fine
Aside from not using a vector of vector in the first place, by starting with the format the API expects? No. There is not a simpler method.

I mean, depends on what you mean by "more simple". If the goal is to make the DrawLine3D function simpler, then you could change your DrawLine3D function take in some wrapper object, where the wrapper would be something like:

1
2
3
4
struct Image {
    vector<unsigned int> Pixels;
    int width;
};


Then
1
2
3
4
5
6
7
8
9
10
11
void DrawLine3D(Image& image, Position3D Origin, Position3D Destination, COLORREF Color)
{
    std::vector<Position3D> GetLineDots = GetLinePoints(Origin, Destination);
    for(int x=0; x<GetLineDots.size()-1; x++)
    {
        unsigned int X = GetLineDots[x].PosX;
        unsigned int Y = GetLineDots[x].PosY;

        image.Pixels[Y * image.width + X] = Color;
    }
}


And you can still use Image::Pixels in conjunction with StretchDIBits.
StretchDIBits( /* ... */, (void*)my_image.Pixels.data(), /* ... */);

And just to clarify keskiverto's second to latest post: VoidPixels is in fact one contiguous array under the hood, so you now can do (void*)VoidPixels.data() without segfaulting.
Last edited on
thank you so much for all.
i will do another topic.
after several suggestions, i did 1 nice Bitmap class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class Bitmap
{
    public:
        unsigned int Width =0;
        unsigned int Height =0;
        unsigned int *Pixels=NULL;
        BITMAPINFO BitInfo;

        Bitmap(unsigned int SizeWidth, unsigned int SizeHeight, COLORREF NewColor=RGB(0,0,0))
        {
            New(SizeWidth,SizeHeight,NewColor);
        }

        void New(unsigned int SizeWidth, unsigned int SizeHeight, COLORREF NewColor=RGB(0,0,0))
        {
            if(Pixels==NULL) free(Pixels);
            Pixels = (unsigned int*) malloc(SizeWidth*SizeHeight*sizeof(unsigned int));
            Width = SizeWidth;
            Height = SizeHeight;
            memset(Pixels,NewColor, sizeof(&Pixels));
            BitInfo.bmiHeader.biSize = sizeof(BitInfo.bmiHeader);
            BitInfo.bmiHeader.biWidth = Width;
            BitInfo.bmiHeader.biHeight = -Height;
            BitInfo.bmiHeader.biPlanes = 1;
            BitInfo.bmiHeader.biBitCount = 32;
            BitInfo.bmiHeader.biCompression = BI_RGB;
        }

        void Draw(HDC Destination, int PosX, int PosY)
        {
            StretchDIBits(Destination, PosX, PosY, Width, Height, 0,0, Width, Height,Pixels, &BitInfo,DIB_RGB_COLORS, SRCCOPY );
        }

        void SetPixel(int PosX, int PosY, COLORREF Color)
        {
            Pixels[PosY*Height + PosX] = Color;
        }

        COLORREF SetPixel(int PosX, int PosY)
        {
            return Pixels[PosY*Height + PosX];
        }

        void DrawLine3D(Position3D Origin, Position3D Destination, COLORREF Color)
        {
            std::vector<Position3D> GetLineDots = GetLinePoints(Origin, Destination);
            for(unsigned int x=0; x<GetLineDots.size()-1; x++)
            {
                unsigned int PosX = GetLineDots[x].PosX;
                unsigned int PosY = GetLineDots[x].PosY;

               Pixels[PosY*Height + PosX] =(unsigned int) Color;
            }
        }
};

i have some errors.... but i will create a new topic.
what i have learned here was: 'void *' it's a 1D array pointer.
thank you so much for all to all.. thank you
void * is one dimensional because it has only one *
just like int * is one dimensional because one *

a void pointer is a pure, raw memory address that holds *something* but you have no idea what that *something* actually is. The type information must be stored on the side, or in a common offset (eg, the first 4 bytes as a type code integer) inside the pointer. This is used a lot in C to do the things we do other ways in c++. An example is older thread library will often take a void * parameter to the function that is being threaded. It does not care: you give it a function and a struct full of parameters via a void pointer, and your function itself accepts the void * and knows what it is supposed to be, and reassembles it into useful info.
1
2
3
4
5
6
7
8
9
10
eg struct s {int x, double d};
void foo(void * vp)
{
   s* sp = (s*) vp;
   cout << sp.x << sp.d << endl;
}
...
s params; 
...
threadthingy th = createthread(foo, &params); 

^^^ the thread library does not care what params really is. any object will do. it just passes through the thread tools and back to your function! foo knows what it really is because the programmer knew what it is, and all is well.


C tools often take void*s that are raw bytes, eg memcpy, memset, etc. Or sometimes they expect char* or whatnot but you are hard casting whatever data into that, eg for a file write of raw bytes. These are generally low level C tools that strip everything down to a pile of bytes out in memory, that YOU the coder know what those bytes mean, and you the coder have to make sense of it -- the C tools don't care what it is, its bytes in memory, and that is all it knows. C++ is a little smarter than that.
Last edited on
thank you so much for all to all
If your width equals your height, it doesn't matter, but otherwise, I'm pretty sure you want
 
Pixels[PosY*Width+ PosX] = Color;

not
 
Pixels[PosY*Height + PosX] = Color;
ganado.. thanks for the correction ;)
Topic archived. No new replies allowed.