2016-06-30 15 views
1

Ich habe die Aufgabe, eine DLL mit vielen Funktionen zu erstellen. Die spezifische Implementierung der Funktionen ist eigentlich ziemlich einfach, aber das allgemeine (oder besser: anfängliche) Setup bereitet mir Kopfschmerzen und ich konnte noch keinen Sinn daraus machen. So sind hier zwei (der vielen) Funktionen soll ich implementieren:Win32 DLL/Referenz speichern

long initClient(long* client, char* a = "", char* b = ""); 
long clientSet(int client, const char* a, const char* b); 

Die erste Funktion wird das Setup ein Client (es kann 0..n sein, jeder Kunde hat interne Zustandsdaten), ist es so irgendwie müssen intern die kundenbezogenen Daten verfolgen. Jetzt, wenn ich clientSet (die zweite Funktion) anrufe, muss ich den Integer-Wert (long * client) übergeben, den ich von initClient an die Funktion erhalte, damit er die korrekte Client-Datenstruktur identifizieren und genau diese Daten ändern kann.

Die eigentliche Frage ist jetzt: Wie mache ich das richtig?

Meine aktuelle Lösung wäre, eine interne Liste von Clients mit ihren zugehörigen Daten/ID zu halten und malloc/free zu verwenden, wenn ein Client hinzugefügt oder entfernt wird. Ich habe jedoch das Gefühl, dass dies keine saubere Lösung ist oder dass es besser gelöst werden könnte.

Ihre Hilfe wird sehr geschätzt.

EDIT: Könnte es sein, dass der erste Parameter von clientSet tatsächlich der Zeiger ist, den ich von initClient (erster Parameter) bekomme? Wenn dies der Fall wäre, müsste initClient nur etwas Speicher mallokieren und diesen mit Daten füllen. Alle anderen Anrufe würden dann nur auf diesen Speicherbereich verweisen. Dennoch finde ich es sehr mühsam, verschiedene Datentypen für den gleichen Zeiger zu verwenden (ich bekomme einen Zeiger auf eine lange, die ich dann als int interpretieren muss - ich verstehe, dass beide 4 Byte auf Win32 sind). Bin ich hier?

EDIT # 2: Leider darf ich die Schnittstelle in keiner Weise ändern.

EDIT # 3: Nach mehr über dieses Problem nachzudenken, vielleicht ist das, was nach dem ich eigentlich bin:

intptr_t my_ptr; 

long initClient(intptr_t* client, char* a, char* b); 
long clientSet(intptr_t client, char* a, char* b); 

initClient (& my_ptr, "A", "B") würde im Grunde (I müssen zu sehen, wie die de-Referenzierung richtig zu tun) machen einen

*client = (intptr_t)malloc(sizeof(myDataStructure)); 

Jetzt konnte ich rufen

clientSet(my_ptr, "X", "Y"); 

Sieht das so aus, als könnte es sein, was ich tun soll?

+2

Ich schlage vor, Sie 2 Dinge: 1) veröffentlichen Sie einige Code mit Ihrer Frage, 2) eine Schnittstelle mit allen Client-bezogenen Methoden, eine Klasse in DLL implementieren diese Methoden und EXPORT nur eine Funktion, die diese Methode, auf diese Weise: __declspec (dllexport) client_interface * GetClientManager(); –

+0

@ GerardoSánchez: Leider bin ich nicht erlaubt, die Schnittstelle zu ändern, fügte ich auch einige Klarstellungen hinzu. Wie für den Code: Ich habe noch keine. Ich würde gerne verstehen, wie man das "richtig" macht, bevor ich überhaupt anfange, etwas zusammen zu hacken. –

+1

Sie exportieren C-Funktionen, aber Sie können sie mit C++ implementieren. In diesem Fall können Sie alle erforderlichen Container (std :: map) verwenden, um Ihre Daten für jeden Client zu speichern. – AnatolyS

Antwort

2

Sie müssen C-Funktionen exportieren, aber Sie können sie mit C++ implementieren. In diesem Fall können Sie alle erforderlichen Container und Datentypen (std :: map, std :: string) verwenden, um die Daten für jeden Client beizubehalten. Wie man dort sehen kann, ist keine jede malloc:

struct client { 
    std::string a; 
    std::string b; 
}; 

std::map<long, client> clients; 

extern "C" { 
    long initClient(long* clientid, char* a = "", char* b = "") { 
    // if you need generate clientid you can use static atomic long 
    static std::atomic_long id(0); 
    clients[*clientid = ++id] = client{ a, b }; 
    return *clientid; 
    } 
    long clientSet(int clientid, const char* a, const char* b) { 
    clients[clientid] = client{ a, b }; 
    return clientid; 
    } 
} 
0

Nach sorgfältiger Prüfung (und einige Diskussionen), haben wir beschlossen, die folgende Art und Weise zu gehen:

  • initClient erzeugt einen malloc'ed Speicherbereich und kehrt der Zeiger auf diese Instanz (die dann als int verwendet wird, die ein Problem in der Zukunft sein könnte, aber das ist derzeit in Diskussion)
  • Alle Funktionen auf diesem malloc'ed Bereich arbeiten
  • eine zusätzliche endClient Funktion wurde hinzugefügt, Frei ist das reservierte Mem ory Raum.

Anscheinend ist das wirkliche Problem hier, ein int als Speicher für einen Zeiger zu verwenden.