2017-12-28 14 views
3

Ich programmiere in einer "Hochsprache" (Nim), und ich muss aus Leistungsgründen auf "C" gehen. Ich möchte so etwas wie dies tun:Wie rufe ich eine C-Funktion auf, die nur in bestimmten Betriebssystemversionen verfügbar ist?

/* Pseudocode */ 
include <VersionHelpers.h> 
/* ...*/ 
if (isWindows8OrGreater()) { 
    /** use InterlockedIncrementNoFence64() */ 
} else { 
    /** use InterlockedIncrement64() ;(*/ 
} 

Aber mir wurde gesagt, es 7 unter Windows abstürzen würde, denn wenn ich InterlockedIncrementNoFence64 Referenz(), es verfügbar sein muß, auch wenn ich nicht versuchen, es zu nennen .

Ich schreibe eine Multi-Thread-App, und die Kommunikation wird mit "Nachrichten" (sogar innerhalb des gleichen Threads) implementiert. Dies wird für jede Nachricht aufgerufen, sodass ein Memory Fence erhebliche Auswirkungen auf die Leistung hat.

Ich bin zu Java verwendet, wo Dinge wie diese Arbeit, und IDK, wie dies in C erfolgt

+2

Führen Sie die entsprechenden Prüfungen zur Kompilierungszeit durch, indem Sie Preprozessor-Makros verwenden, die nicht zur Laufzeit mit Funktionen arbeiten. – alk

+0

Sie meinen also, die Lösung besteht darin, verschiedene Versionen basierend auf dem Ziel-Betriebssystem zu erstellen? Wenn dies der richtige Weg ist, warum posten Sie es nicht als Antwort? –

+1

Verwenden Sie die [Linker-Unterstützung für verzögerungsgeladene DLLs] (https://msdn.microsoft.com/en-us/library/151kt790.aspx). Es müssen keine verschiedenen Versionen erstellt werden, und es wird berichtet, dass Sie einen Fehler beim Auflösen eines Imports zur Verbindungszeit nicht beheben können.Seien Sie immer skeptisch, wenn ein Linux-Entwickler Lösungen zum Linken in Windows vorschlägt. Sie sind im Allgemeinen falsch (wie in diesem Fall). – IInspectable

Antwort

2

in konkretem Fall InterlockedIncrementNoFence64 nicht von einer DLL importiert, sondern implementiert einen Compiler intrinsische auf den meisten Plattform (x86 - via _InterlockedCompareExchange64, Amd64 - _InterlockedIncrement64, Arm/arm64 - _InterlockedIncrement64_nf). so Code mit diesem konkreten Aufruf wird Arbeit an jeder Windows-Version sein (in Win7 sowie natürlich).

im allgemeinen Fall, wenn wir mehrere Funktionen verwenden müssen, die nicht auf allen os exportiert wird - wir können es als Funktionszeiger deklarieren und in Laufzeit auflösen. beispielsweise lassen LoadPackagedLibrary api nehmen

wir Funktionszeiger erklären können:

HMODULE (WINAPI * LoadPackagedLibraryAddr)(
            _In_  LPCWSTR lpwLibFileName, 
            _Reserved_ DWORD Reserved 
            ); 

resolve es in Laufzeit:

*(void**)&LoadPackagedLibraryAddr = GetProcAddress(
    GetModuleHandleW(L"kernel32"), "LoadPackagedLibrary"); 

und Verwendung:

if (LoadPackagedLibraryAddr) 
{ 
    LoadPackagedLibraryAddr(L"***",0); 
} 
else {...} 

eine andere Art und Weise, für die Funktion, die mit __declspec(dllimport) deklariert wurde (die meisten Windows API mit deklariert Dieses Präfix) verwenden nächste Syntax:

aber beide Möglichkeiten erzeugen absolut gleichen Binärcode, nur unterschiedliche Syntax verwenden.

beachten Sie, dass keine Abfrage Windows-Version überhaupt brauchen, einfach versuchen, Zeiger auf API zu bekommen. oder wir bekommen es und können es benutzen, oder nein.

die Art und Weise mit __declspec(selectany) oder #pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue")

wird nicht hier arbeiten, weil damit wir Symbole Link Zeit lösen (Ergebnis wird für alle Windows-Version gemeinsam sein), aber wir brauchen eigentlich Symbol bei Lauf lösen -Zeit.

Verwandte Themen