www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Best way to call external function from another process memory?

reply Skuzzi <tobias2222 hotmail.com> writes:
Hi, I am new to D and I want to use it to create some tools that 
call certain functions from the process of a game, using an 
injected DLL written in D. I have reverse engineered the 
addresses and arguments of the function. Typically this kind of 
stuff is done with C++ and almost all the available resources 
online focus on C++. I was not able to find anything specific to 
this done in D.

This is what a function prototype might look like in C++:
typedef void (__stdcall* _function) (const char *text);
_function function;

Which you would then call using the address of the function in 
memory:
function = (_function)(ADDRESS_OF_FUNCTION);
function("Some text");

I want to do this in D. I understand that D uses "extern (C)" and 
does away with specifying calling conventions. However, how does 
D know the calling convention required? What if it is a 
__thiscall or something else, will it always be handled properly 
by D, just be specifying "extern (C)"?

Does anyone know of a proper and recommended way to achieve this 
in D? Or is this a task better suited for C++? I hope to be able 
to use D for this, as I am enjoying learning the language. Any 
help is deeply appreciated, thank you very much.
Nov 23
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 23/11/2017 11:35 AM, Skuzzi wrote:
 Hi, I am new to D and I want to use it to create some tools that call 
 certain functions from the process of a game, using an injected DLL 
 written in D. I have reverse engineered the addresses and arguments of 
 the function. Typically this kind of stuff is done with C++ and almost 
 all the available resources online focus on C++. I was not able to find 
 anything specific to this done in D.
 
 This is what a function prototype might look like in C++:
 typedef void (__stdcall* _function) (const char *text);
 _function function;
alias _function = extern(C) void function(const(char)* text); _function myFunction;
 Which you would then call using the address of the function in memory:
 function = (_function)(ADDRESS_OF_FUNCTION);
 function("Some text");
void* ADDRESS_OF_FUNCTION = ...; myFunction = cast(_function)ADDRESS_OF_FUNCTION; myFunction(cast(const(char)*("Some text".ptr)); Literals have a \0 at the end so this is safe.
 I want to do this in D. I understand that D uses "extern (C)" and does 
 away with specifying calling conventions. However, how does D know the 
 calling convention required? What if it is a __thiscall or something 
 else, will it always be handled properly by D, just be specifying 
 "extern (C)"?
extern takes care of calling conventions and mangling for declarations (which you are not using in the above). See[0] point 3 regarding how this all works. [0] https://dlang.org/spec/interfaceToC.html#calling_c_functions
Nov 23
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 23 November 2017 at 11:35:18 UTC, Skuzzi wrote:
 typedef void (__stdcall* _function) (const char *text);

 I want to do this in D. I understand that D uses "extern (C)" 
 and does away with specifying calling conventions. However, how 
 does D know the calling convention required? What if it is a 
 __thiscall or something else, will it always be handled 
 properly by D, just be specifying "extern (C)"?
extern(C) is for __cdecl functions. For __stdcall, it is `extern(Windows)`. D doesn't actually do away with calling conventions, it just specifies them with slightly different syntax. You do still wanna make sure you get the right one.
 Does anyone know of a proper and recommended way to achieve 
 this in D?
Generally speaking, if you can do it in C or C++, it isn't *that* much different to do in D: the concepts are the same, just the syntax is slightly different. So the C function pointer (*foo)(arg) stuff turns into a D function pointer: `return_type function(args)` where `function` is the literal keyword `function`. The calling convention turns into one of the correct `extern` on the outside of it: `extern(C)`, `extern(C++)`, `extern(Windows)`, `extern(Pascal)`, or extern(System) and, for completeness, extern(D). The name is based on which language uses that calling convention by default. Then casts go from (type)(statement) to `cast(type)(statement)`; the addition of the `cast` keyword. And a few other little things like array from `int foo[]` to `int* foo` - use pointers for calling C functions instead of D arrays. and C's `long` is not the same as D's `long`, use `import core.stdc.config;` and the type `c_long` instead. otherwise... pretty straightforward one-to-one translation of the concepts described in C++ on the 'net over to D syntax should get you there. You can call the same Windows API functions too.
Nov 23