2016-03-07 2 views
8

Wenn ich eine Funktion in einer .c wieKann jemand manuell Namen in Visual C++ magen?

haben
void foo(int c, char v); 

... in meinem OBJ, wird dies ein Symbol namens

_foo 

... gemäß C Name Mangeln Regeln. Wenn ich eine ähnliche Funktion in einer CPP-Datei habe, wird dies etwas ganz anderes, wie bei den compilerspezifischen Regeln für die Namensänderung. msvc 12 wird uns dies:

[email protected]@[email protected] 

Wenn ich diese Funktion foo in der CPP-Datei und ich möchte es C Namen Mangeln Regeln verwenden (vorausgesetzt, ich ohne Überlastung tun kann), können wir es erklären, wie

extern "C" void foo(int c, char v); 

... in diesem Fall sind wir gute alte

zurück
_foo 

... in der OBJ-Symboltabelle.

Meine Frage ist, ist es möglich, in die andere Richtung zu gehen? Wenn ich C++ - Namensverfälschung mit einer C-Funktion simulieren wollte, wäre dies mit gcc einfach, da die gcc-Namensveränderungsregeln nur kennzeichnungsfreundliche Zeichen verwenden, daher wird der zerlegte Name von foo _ZN3fooEic und wir könnten leicht

schreiben
void ZN3fooEic(int c, char v); 

Zurück in Microsoft-Compiler-Land, ich kann natürlich nicht mit einer Funktion, dessen Namen eine vollständig ungültig Kennung

void [email protected]@[email protected](int c, char v); 

... aber ich würde immer noch wie diese Funktion mit zeigen, genannt erstellen dieser Symbolname in der OBJ-Symboltabelle.

Irgendwelche Ideen? Ich habe die unterstützten Pragmas von Visual C++ durchgesehen und sehe nichts Nützliches.

+3

@mustafagonul Ich bin nicht zu demangle versuchen - ich mangle bin versucht. –

+2

Auch wenn Sie dies tun könnten, müssten Sie irgendwie die ABI übereinstimmen. Du bellst hier den falschen Baum an. Verwenden Sie dafür extern "C" und akzeptieren Sie die Einschränkungen. – xaxxon

+2

@mustafagonul Du verstehst das nicht ganz. Ich weiß, was der verstümmelte und nicht gemanagte Name ist. Ich möchte C++ - Namensmangel in einer C-Datei vortäuschen. –

Antwort

5

Sie können diese __identifier mit tun:

#include <stdio.h> 

#pragma warning(suppress: 4483) 
extern "C" void __cdecl __identifier("[email protected]@[email protected]")(int c, char v) 
{ 
    printf("%d %c\n", c, v); 
} 

void __cdecl foo(int, char); 

int main() 
{ 
    foo(10, 'x'); 
} 
+0

Haben Sie Grund zu der Annahme, dass das tatsächlich funktioniert? Ich habe es gerade versucht, es akzeptiert nur C++ - Schlüsselwörter, keine willkürlichen Zeichenfolgen. –

+1

@TurkeyMan Es funktioniert. Die '#pragma Warnung (suppress: 4483)' ist erforderlich. Wenn Sie das weglassen, erhalten Sie 'Warnung C4483: Syntaxfehler: erwartetes C++ - Schlüsselwort ', was standardmäßig ein Fehler ist. –

+0

@JamesMcNellis das ist genau das, was ich gesucht habe.So erfinderisch der Ansatz von KemyLand auch ist, ich denke, ich werde die akzeptierte Antwort auf diese umstellen (und natürlich beide dieser exzellenten Antworten stimmen). –

7

Sie haben Recht. Das ist nicht (direkt) möglich (Achtung: vertraue VSC++ nie). Es gibt jedoch eine nette Problemumgehung, wenn Sie dies wirklich benötigen. Vor allem in der C++ Datei ...

extern "C" int proxy(int i, char c); 

int foo(int i, char c) 
{ 
    return proxy(i, c); 
} 

Dann wird in der C-Datei ...

int proxy(int i, char c) 
{ 
    // Do whatever you wanna do here 
} 

Ohne einen verstümmelten Namen überhaupt eingeben zu müssen, können Sie jetzt anrufen die foo Funktion, die eigentlich nur ein Wrapper um die C-Funktion proxy ist. Dies gibt Ihnen den gleichen Effekt, als ob proxy eigentlich foo wäre, aus der Sicht von C++. Die einzige Strafe hier ist natürlich ein kurzer 'n' schmutziger Funktionsaufruf. Wenn der ABI dies zulässt und der Compiler intelligent genug ist, kann dies durch eine einzige JMP x86-Anweisung ersetzt werden.

Eine andere Möglichkeit wäre, eine Funktion foo in C, zu schreiben und dann die Verwendung MinGW objcopy, um das Symbol zu umbenennen ...

$ objcopy --redefine-sym "[email protected]@[email protected]" foobar.obj 

Ich bin nicht sicher, ob das möglich ist nur mit VSC++ Tools. Es wäre sowieso sehr instabil, unportabel und hacky.

+1

Es ist nicht ganz das, was ich aus einer Reihe von Gründen wollte, die mit Funktionsprologs zu tun haben, aber es könnte die einzige Lösung sein. –

+1

@TedMiddleton: Siehe die Bearbeitung. Es gibt tatsächlich eine andere Lösung. – 3442

+1

Die Verwendung von Objcopy in Mingw klingt eigentlich nach einer ziemlich guten Lösung. Vielen Dank! –

6

Sie könnten es mit einer. DEF-Datei arbeiten. Definieren Sie Ihre Funktion in Ihrem foo.cpp:

void foo(int c, char v) { ... } 

Dann eine def file an den Linker übergeben, die wie folgt aussieht:

LIBRARY mylib 
EXPORTS 
    [email protected]@[email protected]=_foo 

Haftungsausschluss: nicht getestet, könnte ich einige Details fehlen.

+0

Ich habe momentan nur Zugriff auf MSVC2008 und diese Lösung * funktioniert nicht *. Im Grunde interpretiert der Linker das "@" in der Def-Datei als Sonderzeichen, daher ist das resultierende exportierte Symbol nur "? Foo". Vielleicht hat sich das in einer neueren Version des Compilers geändert. – sbabbi

+0

Ich habe dies auch auf MSVC2013 versucht, und es funktioniert nicht - wie Sie gesagt haben, schneidet es beim ersten '@' Zeichen ab. Du würdest denken, dass es daran lag, dass der Linker das @ -Zeichen mit dem Ordnungsfeld verwechselte, aber es ist nicht - wenn ich ein Symbol wie "? Foo @@ YAXHD @ Z = _foo @ 24" habe, wie du es bekommst Foo, aber es bekommt immer noch die richtige Ordinalzahl, 24. –

Verwandte Themen