Frage

Erstellt Basic C ++ DLL und exportierte Namen mit der Moduldefinitionsdatei (mydll.def). Nach der Kompilierung überprüfe ich die exportierten Funktionsnamen mithilfe mit dumpbin.exeIch erwarte zu sehen:

SomeFunction

Aber ich sehe das stattdessen:

SomeFunction = SomeFunction@@@23mangledstuff#@@@@

Wieso den?

Die exportierte Funktion erscheint nicht dekoriert (insbesondere im Vergleich zur Verwendung der Modul -DEF -Datei), aber was ist mit den anderen Zügen los?

Wenn ich benutze dumpbin.exe Gegen eine DLL von jeder kommerziellen Anwendung erhalten Sie die saubere:

SomeFunction

und sonst nichts...

Ich habe auch versucht, die Moduldefinition zu entfernen und die Namen mit dem Exportstil "C" zu exportieren, nämlich:

extern "C" void __declspec(dllexport) SomeFunction();

(Einfach mit "externer" C "hat keine exportierte Funktion erstellt)

Dies schafft jedoch immer noch die gleiche Ausgabe, nämlich:

SomeFunction = SomeFunction@@@23mangledstuff#@@@@

Ich habe auch das ausprobiert #define dllexport __declspec(dllexport) Option und erstellte eine LIB ohne Problem. Ich möchte jedoch keine LIB -Datei an Personen zur Verfügung stellen, die die DLL in ihrer C# -Anwendung verwenden.

Es ist eine einfache Vanille -C ++ - DLL (nicht verwaltetes Code), zusammengestellt mit C ++, nichts anderes als ein einfacher Header und Code. Ohne Modul definiere ich defekte exportierte Funktionen (ich kann eine statische Bibliothek erstellen und das LIB ohne Problem verwenden. Ich versuche das zu vermeiden). Wenn ich benutze extern "C" __declspec(dllexport) ODER Eine Moduldefinition Ich bekomme einen scheinbar unkonstruktiven Funktionsnamen ... Das einzige Problem ist, dass ein "=" und eine dekorierte Version der Funktion folgt. Ich möchte das Zeug nach dem "=" loswerden oder zumindest verstehen, warum es da ist.

Ich bin mir ziemlich sicher, dass ich die Funktion mit C# mit einem P/Invoke aufrufen kann ... Ich möchte diesen Müll am Ende des "=" nur vermeiden.

Ich bin offen für Vorschläge, wie Sie die Projekt-/Compiler -Einstellungen ändern können, aber ich habe gerade die Standard -Visual Studio DLL -Vorlage verwendet - nichts Besonderes.

War es hilfreich?

Lösung

Sie können das bekommen, was Sie wollen, indem Sie die Debug -Info -Generation ausschalten. Projekt + Eigenschaften, Linker, Debugging, Debugg info = Nr. Nr.

Natürlich möchten Sie dies nur für den Veröffentlichungsgebäude tun. Wo die Option bereits so eingestellt ist.

Andere Tipps

Anstatt die .DEF -Datei zu verwenden, fügen Sie einfach ein pragma comment so was

#pragma comment(linker, "/EXPORT:SomeFunction=_SomeFunction@@@23mangledstuff#@@@@")

Bearbeiten: Oder noch einfacher: im Körper der Funktionswendung

#pragma comment(linker, "/EXPORT:"__FUNCTION__"="__FUNCDNAME__)

. . . Wenn Sie Probleme haben, den dekorierten Funktionsnamen zu finden. Diese letzte Pragma kann mit einer einfachen Makrodefinition weiter reduziert werden.

Sie müssen die Funktionen als deklarieren als extern "C" Wenn Sie nicht möchten, dass ihre Namen verstümmelt werden.

Seien Sie vorsichtig, wenn Sie verwenden __stdcall in Ihrer Funktionssignatur. Mit __stdcall, Der Name bleibt bis zu einem gewissen Grad verstümmelt (Sie werden es schnell genug herausfinden). Anscheinend gibt es zwei Stufen des Mangelns, eine der extern "C" befasst sich auf c ++ - es befasst __stdcall. Das zusätzliche Schrägling ist anscheinend für die Überlastung relevant - aber ich bin mir nicht sicher.

Tut mir leid, dass ich auf einen alten Thread geantwortet habe, aber was als Antwort markiert wurde, hat für mich nicht funktioniert.

Wie eine Reihe von Menschen betont hat, ist die externe "C" -Dekoration wichtig. Das Ändern der Einstellung "Projekte / Eigenschaften / Linker / Debugging / Generate Debugg Info" machte absolut keinen Unterschied zu den verstümmelten Namen, die für mich im Debug- oder Release -Build -Modus generiert wurden.

Setup: VS2005 Kompilieren eines visuellen C ++ -Klbbibliotheksprojekts. Ich habe die kompilierte .dll -Ausgabe mit Microsofts Abhängigkeits -Walker -Tool überprüft.

Hier ist ein Beispielrezept, das für mich funktioniert hat ...

In project.h:

#define DllExport extern "C" __declspec( dllexport )

DllExport bool API_Init();
DllExport bool API_Shutdown();

In Project.cpp:

#include "project.h"

bool API_Init()
{
  return true;
}

bool API_Shutdown()
{
  return true;
}

Anschließend aus C# Managed Code, class.cs:

using System.Runtime.Interopservices;
namespace Foo
{
    public class Project
    {
        [DllImport("project.dll")]
        public static extern bool API_Init();

        [DllImport("project.dll")]
        public static extern bool API_Shutdown();
    }
}

Das Erzielung des oben genannten Verknüpfungsnamens sowohl im Debug- als auch im Release -Modus verhinderte, unabhängig von der Einstellung von Debug -Informationen generieren. Viel Glück.

Auch ohne den Mangeln baut der 32-Bit- und 64-Bit-Namen die Namensnamen-Exporte, selbst mit dem Extern "C", unterschiedlich. Probieren Sie es mit Depends.exe aus.

Dies kann für jeden Client, der eine Lastlibrary+getProcadress durchführt, große Probleme bedeuten, um auf Ihre Funktion zuzugreifen.

Außerdem verwenden Sie also eine Moduldefinitionsdatei wie folgt:

LIBRARY MYDLL
EXPORTS
myFunction=myFunction

Yeap, es ist ein bisschen schmerzhaft zu pflegen, aber wie viele exportierte Funktionen schreiben Sie einen Tag?

Darüber hinaus ändere ich normalerweise die Makros wie unten gezeigt, da meine DLLs -Exportfunktionen keine C ++ - Klassen und ich möchte, dass sie von den meisten Programmierumgebungen aufgerufen werden:

#ifdef WTS_EXPORTS
#define WTS_API(ReturnType) extern "C" __declspec(dllexport) ReturnType WINAPI
#else
#define WTS_API(ReturnType) extern "C" __declspec(dllimport) ReturnType WINAPI
#endif

WTS_API(int) fnWTS(void);

Die letzte Zeile, die vor ein paar Jahren Visualassistx verwirrt hat, weiß ich nicht, ob sie es jetzt richtig verdaut :-)

Ich weiß, wie oft ich versucht habe, Funktionsnamen mit Code und #Pragma zu erzwingen. Und ich ende immer genau mit der gleichen Sache und verwende am Ende die Moduldefinitionsdatei (*.def). Und hier ist der Grund:

//---------------------------------------------------------------------------------------------------
// Test cases built using VC2010 - Win32 - Debug / Release << doesn't matter
//---------------------------------------------------------------------------------------------------
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = Yes (/DEBUG)
//  || (or, also doesn't matter)
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = No + delete PDB file!

extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback

extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> _SetCallback@4

__declspec(dllexport) void SetCallback(LPCALLBACK function);
> ?SetCallback@@YAXP6AXHPADPAX@Z@Z

__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> ?SetCallback@@YGXP6GXHPADPAX@Z@Z    

//---------------------------------------------------------------------------------------------------
// this also big is nonsense cause as soon you change your calling convention or add / remove
// extern "C" code won't link anymore.

// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);

// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback=SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);

// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=_SetCallback@4")
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);

// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback@@YAXP6AXHPADPAX@Z@Z")
__declspec(dllexport) void SetCallback(LPCALLBACK function);

// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback@@YGXP6GXHPADPAX@Z@Z")
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);

//---------------------------------------------------------------------------------------------------
// So far only repetable case is using Module-Definition File (*.def) in all possible cases:
EXPORTS
  SetCallback

extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback

extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback

__declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback

__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback

// And by far this is most acceptable as it will reproduce exactly same exported function name 
// using most common compilers. Header is dictating calling convention so not much trouble for
// other sw/ppl trying to build Interop or similar.

Ich frage mich, warum niemand das getan hat, es brauchte nur 10 Minuten, um alle Fälle zu testen.

Die ArtfUction @@@ 23mangledstuff#@@@@@@@@@ing ist verstümmelt, um die Typen und Klasse der C ++ -Funktion zu geben. Die einfachen Exporte sind Funktionen, die von C abgerufen werden können, dh in C geschrieben oder in C ++ - in C ++ - Code für extern erklärt werden. Wenn Sie eine einfache Schnittstelle wünschen, müssen Sie die Funktionen, die Sie exportieren Nichtmitglied Funktionen im globalen Namespace.

Wenn Sie Funktionen in C ++ verwenden, enthalten Teile ihrer Namen jetzt ihre Unterschrift und dergleichen, um Sprachmerkmale wie Überladung zu erleichtern.

Wenn Sie eine DLL mit __DECLSPEC (dllexport) schreiben, sollte es auch eine Biokraft erzeugen. Link zu dieser LIB, und Sie werden automatisch verknüpft und die von der CRT registrierten Funktionen zum Startzeit registriert (wenn Sie sich daran erinnert haben, alle Ihre Importe in Exporte zu ändern). Sie müssen nicht über den Namen Mangling wissen, wenn Sie dieses System verwenden.

Für den Fall, dass aus den Hunderten von Waffellinien zum Thema verstümmelte Exporte nicht klar war. Hier ist mein 2C -Wert :)

Nach der Erstellung eines Projekts namens Win32Project2 mit VS 2012 und der Auswahl aller Symbole im Zauberer. Sie sollten 2 Dateien namens Win32Project2.cpp und Win32Project2.H haben

Beide verweisen auf eine exportierbare Beispiele für exportierbare Variable und eine exportierte Beispiel.

In Win32Project2.H haben Sie Folgendes:

#ifdef WIN32PROJECT2_EXPORTS
#define WIN32PROJECT2_API __declspec(dllexport)
#else
#define WIN32PROJECT2_API __declspec(dllimport)
#endif

extern WIN32PROJECT2_API int nWin32Project2;
WIN32PROJECT2_API int fnWin32Project2(void);

Um zu entmangenieren, ändern Sie die letzten beiden Zeilen in externe "C" -Delklärungen in:

extern "C" WIN32PROJECT2_API int nWin32Project2;
extern "C" WIN32PROJECT2_API int fnWin32Project2(void);

In Win32Project2.cpp haben Sie auch die folgenden Standarddefinitionen:

// This is an example of an exported variable
WIN32PROJECT2_API int nWin32Project2=0;

// This is an example of an exported function.
WIN32PROJECT2_API int fnWin32Project2(void)
{
    return 42;
}

Um diese zu entmängen, ändern Sie diese in:

// This is an example of an exported variable
extern "C" WIN32PROJECT2_API int nWin32Project2=0;

// This is an example of an exported function.
extern "C" WIN32PROJECT2_API int fnWin32Project2(void)
{
    return 42;
}

Im Wesentlichen müssen Sie das externe "C" -Prefix vor Erklärungen verwenden, um den Linker zu zwingen, nicht -ähnliche C -Namen zu erzeugen.

Wenn Sie es vorziehen, verstümmelte Namen für diese zusätzliche Verschleierung zu verwenden (falls die Manging -Informationen für jemanden nützlich sind), verwenden Sie "Dumpbin /Exporte Win32Project2.dll" von einer VC -Befehlszeile, um die tatsächlichen Referenznamen zu suchen. Es wird das Formular "? Fnwind32Project2@[Param Bytes]@[Andere Infos] haben. Es gibt auch andere DLL -Anzeigen -Tools, wenn das Ausführen einer VC -Befehlsschale Ihr Boot nicht schwimmt.

Genau warum MS diese Konvention nicht standardmäßig standhält, ist ein Rätsel. Die tatsächlichen Manglinginformationen bedeuten etwas (z.

So importieren Sie die oben genannte DLL -Funktion in ein C# -Projekt (in diesem Fall eine grundlegende C# Windows -Anwendung mit einem Formular mit der Schaltfläche "Taste1") hier ist ein Beispielcode:

using System.Runtime.InteropServices;



    namespace AudioRecApp
    {

      public partial class Form1 : Form
      {
        [ DllImport("c:\\Projects\test\Debug\Win32Projects2.dll")] 
        public static extern int fnWin32Project2();

        public Form1()
        {
          InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
          int value;

          value = fnWin32Project2();
        }
      }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top