Exetools

Exetools (https://forum.exetools.com/index.php)
-   Source Code (https://forum.exetools.com/forumdisplay.php?f=46)
-   -   [C] Winapi Call Dynamically and easily (https://forum.exetools.com/showthread.php?t=18714)

bugficks 04-15-2018 16:17

Quote:

Originally Posted by mcp (Post 113039)
Data races yield undefined behavior, so the worst thing that could happen is that this code produces hard to find bugs/crashes. There is no such thing as "virtually thread safe" ;)

good luck trying to get it to crash :)
anyways, this should fix it:
Code:

    static thread_local lib_map libMap;
Quote:

Originally Posted by dosprog (Post 113041)
There is such a thing as the portability of the source code.

really? feel free to do so. i ve already posted a highly portable version

mcp 04-15-2018 18:48

Well, if the code yields UB, that needs to be fixed since it violates the C++ standard. This code violates assumptions made by the compiler when reasoning about/optimizing your program - I shouldn't have to get your program to crash. Above reasoning should already convince you that this code needs to be fixed.
Also, I would move the caching outside of the function, or simply use a mutex - these are much faster than people usually assume, and always safe.

bugficks 04-16-2018 07:24

i ve never stated that this is thread safe assuming that it is is wrong.
this snippet is thought as c++ type safe replacement for original post.
i agree its not production code where youd better use some loader/lib/functor classes but thats not the purpose of these few lines and neither is original post. its rather for quick testing and only requiring copy&paste a few lines of code.

fwiw this aint thread safe either:
PHP Code:

    if(!(lib GetModuleHandleA(library)))
        
lib _LoadLibraryA(library); 

thread X frees library in between those calls, you ll end up w/ an invalid lib handle. GetModuleHandle does NOT increase ref count.

gigaman 04-19-2018 01:14

It could be changed to GetModuleHandleEx - but there's probably no point in not calling LoadLibrary directly?

bugficks 04-19-2018 07:08

if you simply replace it w/ GetModuleHandleEx or LoadLibrary you ll increase lib ref count every call.

mcp 04-19-2018 16:34

Which is what you want, unless performance is your top priority (likely isn't). You simply have to make sure to invoke FreeLibrary accordingly. That's why I subsequently proposed to make the actual call through a functor which would invoke FreeLibrary in the destructor.

bugficks 04-19-2018 18:05

youre mixing stuff up. that GetModuleHandle/LoadLibrary is from original post and thats C, functor in C w/ destructor?
my c++14 version keeps lib ref count constant, thats the sole purpose of the map (what you call 'cache')
also you want to keep lib loaded as dlls might have some init/deinit functions or keep some state between calls.

so if you want to fix version from original post use GetModuleHandleEx and call FreeLibrary later only if GetModuleHandleEx returned a valid handle.
for my c++ version just use thread_local on map like i ve already said before. this will also fix if a dll uses DLL_THREAD_ATTACH which a mutex does not.

mcp 04-19-2018 19:03

I was referring to the ref count problem: that can be trivially solved by having correct pairing of Load/FreeLibrary (and doing what i proposed earlier with a functor would do the right thing). I do not see how that is solved with the c++14 approach you posted? How are LoadLibrary / FreeLibrary calls matched without leaking library handles?

edit: ah got it, it's the shared pointer that points a custom deleter to FreeLibrary. ok. However, for all practical purposes this just keeps libraries loaded until the thread exits - which may or may not be what you want - you have no control over it.

edit2: to clarify, the functor approach was suggested because it inherently avoids unnecessary API lookups, e.g., if you invoke an API in a loop, you'll do the same lookup over and over again because you have coupled lookup with invocation of the API. The functor approach however decouples lookup from invoking, is thread-safe by definition and doesn't need any synchronization mechanisms.

bugficks 04-19-2018 20:40

w/ thread_local its a per thread map and lib is loaded/freed per thread, if that thread exits is see no problem there. OS lib ref count is the same as it was before thread was entered.

well again, this was just a c++ type safe replacement for original post, nothing more nothing less. if you want to do an uber lib loader youre free to do so :)

if you want to optimize lookup you could as well just add an optional opaque pointer and store some infos there.
e.g.:
PHP Code:

template <typename Ftypename... ArgTypes>
auto DynCallT(void **opaqueLPCTSTR libNameLPCSTR funcNameArgTypes... args)

    if(
opaque && *opaque
    { (
cast_opaque_t)(opaque) ...} 
    ... 
    if(
opaque
    { *
opaque=... }
    ...
}
void *ppp=0;
for(...) 
DynCallT(ppp, ...); 

anyways, it is what it is and it doesnt want to be more :)

aliali 05-08-2018 05:08

Quote:

Originally Posted by bugficks (Post 113073)
w/ thread_local its a per thread map and lib is loaded/freed per thread, if that thread exits is see no problem there. OS lib ref count is the same as it was before thread was entered.

well again, this was just a c++ type safe replacement for original post, nothing more nothing less. if you want to do an uber lib loader youre free to do so :)

if you want to optimize lookup you could as well just add an optional opaque pointer and store some infos there.
e.g.:
PHP Code:

template <typename Ftypename... ArgTypes>
auto DynCallT(void **opaqueLPCTSTR libNameLPCSTR funcNameArgTypes... args)

    if(
opaque && *opaque
    { (
cast_opaque_t)(opaque) ...} 
    ... 
    if(
opaque
    { *
opaque=... }
    ...
}
void *ppp=0;
for(...) 
DynCallT(ppp, ...); 

anyways, it is what it is and it doesnt want to be more :)

Is it possible to have a pure ANSI C implementation of the above code :)

0xall0c 10-17-2018 19:36

Quote:

Originally Posted by aliali (Post 113229)
Is it possible to have a pure ANSI C implementation of the above code :)

not possible, as i know, but there can be work around at lower levels


All times are GMT +8. The time now is 10:13.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX