Windows passing buffer_get_address() to DLL causes c++ System.AccessViolationException

F

Fishman1175

Guest
Hello,

I'm guessing a developer or higher up might need to comment on this. I'm trying to pass the pointer of a buffer I create in GM to my C++ DLL. Now, the help docs say that this can be passed to be used in extensions. Here is the gml code:

buffer_new_map=buffer_create(2097152,buffer_fixed,8)
buffer_pointer=buffer_get_address(buffer_new_map)
simplex_set_buffer_address(real(buffer_pointer))
show_message(string(buffer_pointer))

simplex_set_buffer_address is an external call to my DLL.

Now, in C++ I have:

export double set_buffer_address(double hex_addr)

{
int ptr = (int) hex_addr;
buffer_pointer = reinterpret_cast<double *>(ptr);
ofstream myfile;
myfile.open ("C:\\output.txt");

myfile << buffer_pointer;
myfile.close();
return 1.0;

}

The error that appears in Game Maker's console is:


Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.


at calc_map()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()


The output from the c++ file and the show_message are identical, so I know the memory addresses are the same. Am I just screwed? I don't see why the help doc says I can use the pointer in my extensions if I can't read or write to the data. What else can I try?
 

dphsw

Member
I had problems passing buffers to DLLs too. Your C++ function is receiving a double as an argument, which is what I initially assumed made sense too - that the double could be casted to an int, which being four bytes could be casted to a 32-bit memory address pointer. Whatever the reason, it seems like that doesn't work. (For me the program just crashed, rather than giving a neat error message, but maybe that's because I'm trying to write to the buffer rather than just read from it, or something.) Since C/C++ memory allocation functions like malloc() return char* pointers, I think that's how the pointer is treated in GameMaker - so to pass the output of buffer_get_address to a DLL, I think you have to make that function take a char* argument and tell GameMaker the DLL function takes a string, and GML then seems quite willing to pass the pointer from buffer_get_address without any conversion.

As test code, I have in GameMaker:
Code:
var buff = buffer_create(1,buffer_fast,1);
var mem_addr = buffer_get_address(buff);
GetVertices(mem_addr);
show_debug_message(buffer_peek(buff,0,buffer_u8));
and in my DLL:
Code:
double GetVertices(char* memaddr) {
    memaddr[0] = 'a';
    return 0;
}
And the output console is showing 97 (the ascii code for the 'a').
 

Binsk

Member
As stated above, you should pass in the pointer directly to the DLL. Do not convert it to a real.

As strings are just pointers, mark the DLL output as a string on GameMaker's side. On your dll's side you can mark the input as any kind of pointer.

Inside the DLL you can then treat it like you would any other array and read or set data accordingly.
 

hippyman

Member
As strings are just pointers, mark the DLL output as a string on GameMaker's side. On your dll's side you can mark the input as any kind of pointer.
Sorry to necrobump this topic but I didn't feel like my small question warranted a whole new topic. Do you mean to set the return type to string or the argument type to string?

I'm dumb. I figured it out like ten minutes after I posted this. I knew I should have waited. Sorry to bring you back here for nothing.
 
Last edited:
Top