سؤال

أنا أكتب C/C++ DLL و تريد تصدير بعض المهام التي قمت بها قبل استخدام .مواطنه ملف مثل هذا

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

مع رمز تعريف هذا ، على سبيل المثال:

int Foo(int a);
void Bar(int foo);

ولكن ماذا لو كنت تريد أن تعلن وسيلة طاقتها من فو() مثل:

int Foo(int a, int b);

كما مواطنه الملف يحتوي فقط على اسم وظيفة وليس كامل النموذج لا أستطيع أن أرى كيف سيكون التعامل مع الوظائف مثقلة.هل مجرد استخدام إدخال واحد ثم تحديد طاقتها النسخة التي تريدها عندما يمر في صحيح نموذج أولي مؤشر دالة LoadLibrary() ?

تحرير:أن تكون واضحة, هذا هو على ويندوز باستخدام Visual Studio 2005

تحرير:شهد غير مواطنه (__declspec) طريقة الإجابة...أعلم أن هذا لا يحل المشكلة باستخدام مواطنه الملفات كما أردت ، ولكن يبدو أن هناك احتمالا لا (الرسمية) الحل باستخدام مواطنه الملفات.سوف أترك السؤال مفتوحا ، ومع ذلك ، في حالة شخص ما يعرف شيئا ليس لدينا طاقتها وظائف مواطنه الملفات.

هل كانت مفيدة؟

المحلول

في القانون نفسه ، مارك مهام تريد تصدير باستخدام __declspec(dllexport).على سبيل المثال:

#define DllExport __declspec(dllexport)

int DllExport  Foo( int a ) {
  // implementation
}
int DllExport Foo( int a, int b ) {
  // implementation
}

إذا كنت تفعل هذا, أنت لا تحتاج إلى قائمة وظائف في .ملف def.

بدلا من ذلك, كنت قد تكون قادرة على استخدام قيمة المعلمة الافتراضية, مثل:

int Foo( int a, int b = -1 )

هذا يفترض أن هناك قيمة ب التي يمكنك استخدامها للإشارة إلى أنه غير المستخدمة.إذا -1 هو القيمة القانونية ل ب ، أو إذا لم يكن هناك أو لا ينبغي أن يكون افتراضي, هذا لن يعمل.

تحرير (آدم هايلي):تصحيح لاستخدام __declspec كما __dllspec غير صحيح حتى أتمكن من علامة هذا الجواب الرسمية...كانت قريبة بما فيه الكفاية.

تحرير (غرايم):عفوا شكرا على تصحح لي الخطأ المطبعي!

نصائح أخرى

وظيفة الحمولة الزائدة هي C++ الميزة التي تعتمد على اسم تغيير اسم (خفي وظيفة الأسماء في رسائل خطأ linker).

من خلال كتابة المهترئ الأسماء في الملف def, يمكنني الحصول على بلدي اختبار المشروع إلى ربط وتشغيل:

LIBRARY "TestDLL"
EXPORTS
    ?Foo@@YAXH@Z
    ?Foo@@YAXHH@Z

يبدو أن العمل بالنسبة

void Foo( int x );
void Foo( int x, int y );

حتى نسخ C++ وظيفة الأسماء من رسالة الخطأ كتابتها في ملف def.ومع ذلك ، فإن السؤال الحقيقي هو:لماذا كنت ترغب في استخدام ملف def و لا تذهب مع __declspec(dllexport) ?

المهترئ أسماء غير المحمولة ، اختبرت مع VC++ 2008.

لدي مشكلة مشابهة إذا كنت أرغب في الرد على هذا أيضا.

  1. وعادة ما تستخدم

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

    لتصدير اسم الدالة على ما يرام.وسوف عادة تصدير اسم unmangled دون الحاجة .ملف def.ومع ذلك ، هناك بعض الاستثناءات مثل __stdcall وظائف و وظيفة مثقلة الأسماء.

  2. إذا كنت تعلن عن وظيفة استخدام __stdcall الاتفاقية (كما هو الحال بالنسبة للعديد من وظائف API) ثم

    extern "C" __declspec(dllexport) void __stdcall Foo();
    

    سيتم تصدير المهترئ اسم مثل _Foo@4.في هذه الحالة قد تحتاج إلى صراحة خريطة المصدرة اسم داخلي المهترئ اسم.

A.كيفية تصدير unmangled اسم.في .ملف def إضافة

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

وهذا في محاولة لإيجاد "أفضل مباراة" داخلي وظيفة فو وتصديره.في حالة أعلاه حيث هناك فقط واحدة فو هذا سوف إنشاء الخرائط

فو = _Foo@4

كما يمكن أن نرى من خلال dumpbin /الصادرات

إذا كان لديك طاقتها اسم وظيفة ثم قد تحتاج إلى صراحة أقول أي وظيفة كنت ترغب في .ملف def عن طريق تحديد المهترئ اسم باستخدام entryname[=internalname] بناء الجملة.على سبيل المثال

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

ب.بديلا .مواطنه الملفات التي يمكنك تصدير أسماء "في مكان" باستخدام #pragma.

#pragma comment(linker, "/export:Foo=_Foo@4")

C.البديل الثالث هو أن تعلن إصدار واحد فقط من فو كما extern "C" التي يتم تصديرها unmangled.انظر هنا للحصول على التفاصيل.

لا توجد وسيلة رسمية من فعل ما تريد ، لأن dll واجهة C api.

المترجم نفسه يستخدم المهترئ أسماء كحل, لذلك يجب عليك استخدام اسم من الضغط عندما كنت لا تريد أن تغير الكثير في التعليمات البرمجية الخاصة بك.

ليس هناك لغة أو نسخة الملحد طريقة تصدير وظيفة طاقتها منذ تغيير اسم الاتفاقية يمكن أن تتغير مع كل إصدار من برنامج التحويل البرمجي.

هذا هو السبب في أن معظم WinXX وظائف أسماء غريبة مثل *السابق أو *2.

Systax الصادرات التعريف هو:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]

entryname هي وظيفة أو اسم المتغير الذي تريد تصديره.هذا هو المطلوب.إذا كان الاسم الذي التصدير يختلف عن الاسم في DLL تحديد التصدير اسم DLL مع internalname.

على سبيل المثال ، إذا كان DLL الخاص بك الصادرات وظيفة ، func1() و تريد أن تستخدم func2 () ، أن تحدد:

EXPORTS
func2=func1

فقط انظر المهترئ أسماء (باستخدام التبعية ووكر) وتحديد المهام الخاصة بك اسم.

المصدر: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=مقابل 71).aspx

تحرير:هذا يعمل الديناميكي Dll ، حيث أننا بحاجة إلى استخدام GetProcAddress() صراحة جلب الدالات في Dll.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top