2017-12-29 9 views
1

Ich habe eine einfache Helferbibliothek für ein kleines Spiel, das ich mache, gemacht. In einer solchen Bibliothek habe ich einige Kernfunktionen, die so schnell wie möglich funktionieren müssen, da sie tausende Male pro Spielfeld aufgerufen werden.Symbol duplizieren, wenn Header-Bibliothek mehr als einmal enthalten ist

Wenn ich sie „inline“ erklären und teilen ihre Erklärung (library.h) aus ihrer Umsetzung (library.c) und sie in der Spieldatei (game.c), ich denke, sie sind nicht inlined/optimiert sie direkt in game.c seit erklärt und das Spiel mit gcc -O3 kompilieren gibt mir einen Leistungsschub von mehr als 60 mal.

Um dieses Problem zu lösen, habe ich beschlossen, meine Bibliothek eine Header-Only-Bibliothek zu machen. Ich habe alle meine Framework-Konstanten, Variablen und Funktionen in library.h. Inklusive es in game.c gibt mir immer noch die maximale Leistung.

Nun, das Problem ist, dass, wenn ich library.h in mehr als eine Datei enthalten (zB game1.c und game2.c) ich eine lange Liste von duplicate symbol Fehlern erhalten, wenn das Spiel zu kompilieren. Die Bibliothek hat #pragma once, aber immer noch tritt das Problem auf.

Wie tatsächlich Header-only-Bibliotheken schreiben oder sicherstellen, dass eine Inline-Funktion aus einer externen Bibliothek tatsächlich optimiert ist?

Dank

+3

Definieren * Sie * Variablen oder Funktionen in Ihrer Header-Datei? –

+1

Sie wollen nur die Variablen im Header deklarieren und haben eine separate '.c' Datei für Definitionen – qwn

+0

Sie wollen die Funktionen' static' deklarieren. – alk

Antwort

2

Als Alk bereits kommentiert, müssen Sie static die Funktionen und globale Variablen in der Header-Datei erklären.

Das Schlüsselwort static bedeutet, dass das Objekt (Funktion oder Variable) interne Verknüpfung hat; dass es nur in der aktuellen Kompilierungseinheit sichtbar ist und in keiner Symboltabelle enthalten ist.

Es ist auch eine gute Idee, Wachen zu verwenden sind, so dass, wenn Sie einen anderen Header-Datei, die Ihre Header enthält, und die C-Quelldatei enthält sowohl Ihre Header-Datei und dass andere Header-Datei, nur Ihre Header-Datei enthalten wird Einmal. (Die Linien mit FOOLIB_H umfassen die Wache im folgende Beispiel enthalten.)

Betrachten Sie das folgende triviale feste Größe Stapel Beispiel foolib.h:

#ifndef FOOLIB_H 
#define FOOLIB_H 

#include <stdlib.h> 

#define STACK_MAX 256 

static size_t stack_size = 0; 
static double stack_item[STACK_MAX]; 

static inline int stack_push(const double item) 
{ 
    if (stack_size < STACK_MAX) { 
     stack_item[stack_size++] = item; 
     return 0; 
    } else 
     return -1; 
} 

static inline double stack_pop(const double empty) 
{ 
    if (stack_size > 0) 
     return stack_item[--stack_size]; 
    else 
     return empty; 
} 

#endif /* FOOLIB_H */ 

Jede Übersetzungseinheit (jede Quelldatei (separat kompilieren), das das obige enthält (#include "foolib.h"), erhält ihren eigenen lokalen privaten Stapel, den sie über stack_push() und stack_pop() verwenden können.

Der Grund für die Kennzeichnung der Funktionen static inline anstatt nur static ist, dass der ehemalige dem Compiler sagt, dass es in Ordnung ist, die Funktion ganz wegzulassen, wenn sie nicht verwendet wird. Insbesondere, wenn Sie Code mit gcc -Wall kompilieren, warnt gcc, wenn eine static Funktion nicht verwendet wird, warnt jedoch nicht, wenn eine static inline Funktion nicht verwendet wird. Ansonsten gibt es nicht viel praktischen Unterschied.

Verwandte Themen