ايران ويج

نسخه‌ی کامل: ارتباط دو زبان c و ++C و ایجاد آبجکت از کلاس در C
شما در حال مشاهده‌ی نسخه‌ی متنی این صفحه می‌باشید. مشاهده‌ی نسخه‌ی کامل با قالب بندی مناسب.
سلام
شاید یکم سخت بتونم منظورمو منتقل کنم

2 تاپروژه فرض کنید
یکیش در ++C که قراره بصورت فایل lib.* کامپایل بشه
پروژه دوم هم قراره از همون فایل lib استفاده کنه.


داخل پروژه ++C یه کلاس تعریف شده به فرم زیر
کد:
class MemBufferObject
{
   private:

       char *m_pData;
       int m_size;
       int m_offset;

   public:

       inline MemBufferObject(char *pSource, int size) : m_pData(pSource), m_size(size), m_offset(0) {}

       inline int Read(char *pBuffer, int size)
       {
           // Don't worry about reading partial data here...
           if (m_offset + size <= m_size)
           {
               ::memcpy(pBuffer, &m_pData[m_offset], size);
               m_offset += size;
               return size;
           }

           return -1;
       }
};

کد:
SQInteger BufferRead(SQUserPointer pMemObject, SQUserPointer pDest, SQInteger size)
{
   // Assume that our source is a MemBufferObject
   MemBufferObject *pBuffer = reinterpret_cast<MemBufferObject *>(pMemObject);

   return pBuffer->Read(reinterpret_cast<char *>(pDest), size);
}


و یدونه تابع داریم که در ++C نوشته شده و قراره از C فراخوانی بشه:

کد:
SQRESULT LoadScript(HSQUIRRELVM vm, MemBufferObject *pSource)
{
   return sq_readclosure(vm, BufferRead, (SQUserPointer)(pSource));
}
 
اگر دقت کنید آرگومان دوم تابع از جنس کلاس MemBufferObject هستش
چون این تابع قراره از C فراخوانی بشه، سوالم اینه که چطوری در زبون C (نه ++C) ، از کلاسی که در ++C نوشته شده، یه متغییر درست کنم و به کمک class constructor اون متغییر رو با داده خودم مقدار دهی کنم؟
چند تا سورس کد بررسی کردم، توی هدر فایلی که به خورد برنامه C داده بودن، کلاس رو بصورت struct تعریف کرده بودن
ولی مشکل اینجاست که اگه بصورت struct تعریف بشه، از داخل برنامه C چطوری باید به تابع class constructor ای که در ++C پیاده شده، (از درون برنامه C) دسترسی پیدا کنم؟
لینک هایی که راجب مشکلم پیدا کردم رو اینجا میذارم شاید منظور رو بهتر برسونن:
http://stackoverflow.com/questions/15887...onsumption
http://stackoverflow.com/questions/35833...rom-c-code
بعد 5 ساعت جستجو، کم کم قضیه روشن میشه برام
گوگل 
کد:
C++ Class Wrapping
سرچ کنید


با موفقیت تونستم به توابع داخل کلاس، توسط wrapping functions ؛ از داخل برنامه C دسترسی پیدا کنم.
سلام دوستان

بعد یه مدت این مشکل بطور کامل حل شد

خلاصه ای از تجربه های کسب شده رو وبلاگ نوشتم
لینک:
کلیک کنید



---------------------------------------------------

درود و وقت بخیر
شاید برای شما هم پیش اومده باشه که نیاز داشته باشید به استفاده از static library ای که در زبان ++C که کلاس و آبجکت داره، نوشته شده، در زبان دیگه ای مثل C که کلاس و آبجکت رو پشتیبانی نمیکنه!
خب اینجاست که مفهوم Class Wrapping مطرح میشه.
روشی که بکمک اون، در سمت ++C ساختاری پیاده سازی میشه که از زبان C قابل استفاده باشه.

در ضمن static library در مقابل dynamic library هست. تفاوت این دو که پسوندشون به ترتیب lib و DLL هست، در زمان لود شدنشون به برنامه میزبان هست.
DLL در runtime توسط میزبان load میشه، در حالی که static library موقع بیلد شدن برنامه میزبان، ازش استفاده میشه.

بطور خلاصه هدف class wrapping، ایجاد دسترسی به عضو های کلاسی هست که در سی پلاس تعریف شده(از C به عنوان مثال)
برای اینکار، برای هر تابعی که در کلاس تعریف شده، یک تابع کمکی در خارج از کلاس ایجاد میکنیم. اینا به کنار، 2 تا تابع اضافی دیگه لازم داریم. 
1. تابع ایجاد یک شی از کلاس و برگردوندن اشاره گر بهش در return تابع
2.تابع حذف شی ایجاد شده توسط تابع بالایی

در واقع به کمک این 2 تا تابع، ساختار new <className> رو برای زبانی مثل C که شی گرا نیست، پیاده میکنم.

چندتا لینک خوب که این موضوع رو بررسی کردن، آورذم:


خب حالا بطور خلاصه کارایی که برای یه کلاس ++C لازمه انجام بشه تا در زبان C قابل استفاده باشه رو مرور میکنیم:

این فایل ++C همراه توابع wrapper برای کلاس:

کد:
//myclass_src.cpp
#include "wrapper.h"
class myclass
{

private:

int a,b;

public:

myclass(int init_val_a,int init_val_b)

{

a = init_val_a;

b = init_val_b;

}


int sum()

{

return a+b;

}
}
extern "C" void* myclass_create(int a, int b)
{

return new myclass(a,b);
}
extern "C" void  myclass_destroy(void*cls_ptr)
{

delete static_cast<myclass*>(cls_ptr);
}

extern "C" int myclass_sum(void *cls_ptr)
{

return static_cast<myclass*>(cls_ptr)->sum();
}


حالا چیزی که لازم داریم یه هدر فایل برای استفاده در c هست: 


کد:
//wrapper.h
#ifdef __cplusplus
extern "C" {
#endif
void* myclass_create(int init_val_a,int init_val_b)    ;
void myclass_destroy(void*cls_ptr)       ;
int myclass_sum(void *cls_ptr)       ;
#ifdef __cplusplus
}
#endif


حال سمت C برای استفاده از static lib ای که با پسوند lib.* یا a.* ساخته شده:

باید فایل lib یا a رو به پروژه اضافه کنید(در keil بسادگی با add file کردن به پروژه -- در IAR بطور مشابه -- در ویژوال استودیو : از طریق project properties دنبال گزینه precompiled libraries باشید)
باید هدر فایل wrapper رو در پروژه C مدنظر، include کنید.


کد:
//Pure_C_Project.c
#include "wrapper.h"

int main
{

void* p_myclass;

int sum=-1;

p_myclass = myclass_create(1,3);

//-------------------------------


sum = myclass_sum(p_myclass);


//-------------------------------

myclass_destroy(p_myclass);
}

سوالی بود خوشحال میشم کمکی کرده باشم.
موفق باشید.