Kontekst: Przekształciłem starszy autonomiczny silnik w komponent wtyczki dla narzędzia kompozycji. Z technicznego punktu widzenia oznacza to, że skompilowałem bazę kodu silnika do biblioteki DLL C, którą wywołuję z opakowania .NET za pomocą P/Invoke; wrapper implementuje interfejs zdefiniowany przez narzędzie do komponowania. Działa to całkiem dobrze, ale teraz otrzymuję żądanie załadowania wielu instancji silnika dla różnych projektów. Ponieważ silnik przechowuje dane projektu w zbiorze zmiennych globalnych, a ponieważ biblioteka DLL z podstawą kodu silnika jest ładowana tylko raz, ładowanie wielu projektów oznacza, że dane projektu są nadpisywane.Obsługa wielu wystąpień biblioteki DLL wtyczki z danymi globalnymi
widzę szereg rozwiązań, ale wszystkie one mają pewne wady:
Można utworzyć wiele bibliotek DLL z tego samego kodu, które są postrzegane jako różne biblioteki DLL w systemie Windows, więc ich kod nie jest udostępniony. Prawdopodobnie działa to, jeśli masz wiele kopii DLL silnika o różnych nazwach. Jednak silnik jest wywoływany z opakowania przy użyciu atrybutów
DllImport
i myślę, że nazwa silnika DLL musi być znana podczas kompilowania opakowania. Oczywiście, jeśli muszę skompilować różne wersje opakowania dla każdego projektu, jest to dość kłopotliwe.Silnik może działać jako oddzielny proces. Oznacza to, że owijka uruchomiłaby oddzielny proces dla silnika podczas ładowania projektu i użyłaby jakiejś formy IPC do komunikacji z tym procesem. Chociaż jest to stosunkowo czyste rozwiązanie, to wymaga trochę wysiłku, aby uzyskać pracę, nie wiem, która technologia IPC byłaby najlepsza do stworzenia tego rodzaju konstrukcji. Może również występować znaczny narzut komunikacji: silnik musi często wymieniać tablice liczb zmiennoprzecinkowych.
Silnik można dostosować do obsługi wielu projektów. Oznacza to, że zmienne globalne powinny zostać umieszczone w strukturze projektu, a każde odniesienie do globali powinno zostać przekonwertowane na odpowiadające odniesienie, które odnosi się do konkretnego projektu. Istnieje około 20-30 zmiennych globalnych, ale jak można sobie wyobrazić, te zmienne globalne są przywoływane z całej bazy kodu, więc ta konwersja musiałaby zostać wykonana w sposób automatyczny. Powiązanym problemem jest to, że powinieneś być w stanie odnieść się do "aktualnej" struktury projektu we wszystkich miejscach, ale przekazanie tego jako dodatkowego argumentu w każdym podpisie funkcji jest również uciążliwe. Czy istnieje technika (w języku C) do rozważenia bieżącego stosu wywołań i znalezienia najbliższej instancji zawierającej odpowiednią wartość danych?
Czy społeczność stackoverflow może udzielić porady na temat tych (lub innych) rozwiązań?
Czy nie można zmodyfikować biblioteki DLL silnika, aby miała fabryczną metodę zwracania stanu "globalnego" na żądanie? E.g, podsumować wszystko, co jest obecnie globalne, do obiektu, który można utworzyć, umożliwiając tworzenie wielu silników z pojedynczej biblioteki DLL? –
Jeśli ktoś kiedykolwiek potrzebował powodu, dla którego zmienne globalne są złym pomysłem, skieruj go na to pytanie. – Timbo
@ Moo-Juice: Myślę, że to odpowiadałoby rozwiązanie nr 3? –