لا يمكن الوصول إلى المتغير في C++ DLL من C التطبيق

StackOverflow https://stackoverflow.com/questions/56500

سؤال

أنا عالقة على إصلاح تركة Visual C++ 6 التطبيق.في C++ DLL مصدر لقد وضعت

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

مما يؤدي MyNewVariable تظهر (بشكل غير مزخرف) في تصدير الجدول (كما هو موضح من قبل dumpbin /الصادرات blah.dll).ومع ذلك, لا يمكن معرفة كيفية تعريف متغير بحيث لا يمكن الوصول إليه في ج الملف المصدر.لقد حاولت أشياء مختلفة ، بما في ذلك

_declspec(dllimport) char* MyNewVariable;

ولكن هذا فقط يعطيني رابط خطأ:

حل الرمز الخارجية "__declspec(dllimport) شار * MyNewVariable" (__عفريت_?MyNewVariable@@3PADA)

extern "C" _declspec(dllimport) char* MyNewVariable;

كما اقترح توني (كما حاولت من قبل) النتائج في مختلف المتوقع الديكور, ولكن لا يزال لم إزالته:

حل الخارجية الرمز __عفريت__MyNewVariable

كيف يمكنني كتابة إعلان بذلك أن C++ DLL متغير يمكن الوصول إليها من C التطبيق ؟


الجواب

كما حددها botismarius وغيرها (شكرا جزيلا لجميع), أنا في حاجة إلى الارتباط مع DLL .lib.لمنع اسم المهترئ أنا في حاجة أن يعلن أنه (في المصدر ج) مع أي ديكور ، مما يعني أن كنت بحاجة إلى استخدام .الملف lib.

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

المحلول

يجب ربط ضد lib ولدت بعد تجميع DLL.في رابط خيارات المشروع ، يجب إضافة .lib الملف.و نعم, يجب عليك أيضا أن تقوم بتعريف المتغير كما يلي:

extern "C" { declspec(dllimport) char MyNewVariable; }

نصائح أخرى

extern "C" هو كيف يمكنك إزالة الديكور - العمل على استخدام:

extern "C" declspec(dllimport) شار MyNewVariable;

أو إذا كنت ترغب في الرأس التي يمكن استخدامها من قبل C++ أو C (مع /TC التبديل)

#ifdef __cplusplus
extern "C" {
#endif
declspec(dllimport) char MyNewVariable;
#ifdef __cplusplus
}
#endif

وبالطبع الرابط مع مكتبة الاستيراد التي تم إنشاؤها بواسطة dll القيام التصدير.

لست متأكدا من الذي downmodded botismarius, لأنه على حق.والسبب هو .ليب الناتجة عن استيراد مكتبة يجعل من السهل ببساطة تعلن الخارجية متغير/وظيفة مع __declspec(dllimport) و مجرد استخدامه.استيراد مكتبة ببساطة بأتمتة اللازمة LoadLibrary() و GetProcAddress() المكالمات.دون ذلك, أنت بحاجة إلى استدعاء هذه يدويا.

كلاهما صحيح.حقيقة أن رسالة الخطأ توضح __imp_?MyNewVariable@@3PADA يعني أنه يبحث عن اسم المزين ، لذلك extern "C" ضروري.ومع ذلك ، ربط مع استيراد المكتبة أيضا من الضروري أو عليك فقط الحصول على مختلف الرابط خطأ.

@جرايم:أنت على حق في ذلك أيضا.أعتقد أن "ج" المترجم أن المرجع هو استخدام بإنفاذ C99 القياسية ، ولكن تجميع مثل C++, وبالتالي تغيير اسم أسماء.صحيح ج مترجم لن نفهم "ج" جزء من extern "C" الكلمات الرئيسية.

في dll البرمجية المصدر يجب أن يكون هذا التنفيذ بحيث .الملف lib الصادرات الرمز:

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

ج العميل يجب استخدام رأس مع هذا الإعلان حيث أن العميل سوف رمز استيراد الرمز:

extern "C" _declspec(dllimport) char* MyNewVariable;

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

إذا كنت بحاجة إلى ذلك ، يمكنك أيضا إنشاء "العالمي" رأس التي يمكن تضمينها في أي مكان أن تبدو مثل هذا:

#ifdef __cplusplus
extern "C" {
#endif
#ifdef dll_source_file
#define EXPORTED declspec(dllexport) 
#else
#define EXPORTED declspec(dllimport) 
#endif dll_source_file
#ifdef __cplusplus
}
#endif

EXPORTED char* MyNewVariable;

ثم dll البرمجية المصدر يبدو مثل هذا:

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

والعميل يبدو مثل هذا:

#include "universal_header.h"
...
MyNewVariable = "Hello, world";

إذا كنت تفعل هذا كثيرا ، الوحش #ifdef في أعلى يمكن أن تذهب في export_magic.ح و universal_header.ح يصبح:

#include "export_magic.h"

EXPORTED char *MyNewVariable;

أنا لم تستخدم _declspec(dllimport) عندما كنت في البرمجة في ويندوز.يجب أن تكون قادرة على مجرد إعلان

extern "C" char* MyNewVariable;

و رابط .libb إنشاؤه عند DLL تم تجميعها.

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