Program C++ yang menggunakan header perpustakaan C mengenali ini sebagai kata kunci. Kesalahan C eksternal?

Program C++ saya perlu menggunakan perpustakaan C eksternal. Oleh karena itu, saya menggunakan

extern "C"
{
   #include <library_header.h>
}

sintaks untuk setiap modul yang perlu saya gunakan.

Itu berfungsi dengan baik sampai sekarang. Sebuah modul menggunakan nama ini untuk beberapa variabel di salah satu file headernya. Perpustakaan C sendiri dapat dikompilasi dengan baik karena, dari apa yang saya tahu, ini tidak pernah menjadi kata kunci di C.

Namun meskipun saya menggunakan sintaks extern "C", saya mendapatkan kesalahan dari program C++ saat saya menyertakan file header tersebut.

Jika saya mengganti nama setiap ini di file header perpustakaan C dengan sesuatu seperti _ini, semuanya tampak berfungsi dengan baik.

Pertanyaannya adalah:

Bukankah sintaks extern "C" seharusnya cukup untuk kompatibilitas ke belakang, setidaknya pada tingkat sintaksis, untuk file header? Apakah ini masalah dengan kompiler?


person nyarlathotep108    schedule 03.09.2014    source sumber
comment
Yang dilakukan extern "C" hanyalah memberi tahu kompiler untuk tidak melakukan pengrusakan nama.   -  person Some programmer dude    schedule 03.09.2014
comment
stackoverflow.com/q/1041866/1147772   -  person Drax    schedule 03.09.2014
comment
@JoachimPileborg - extern "C" mengatakan untuk menggunakan nama C mangling, yang biasanya berarti menambahkan garis bawah.   -  person Pete Becker    schedule 03.09.2014
comment
extern "C" tidak secara ajaib mengalihkan bahasa saat ini ke C. Yang terpengaruh hanyalah spesifikasi tautan entitas eksternal. File header Anda masih dikompilasi sebagai kode C++ dan harus mematuhi semua aturan bahasa C++.   -  person AnT    schedule 03.09.2014


Jawaban (4)


Bukankah sintaks "C" eksternal cukup untuk kompatibilitas ke belakang, setidaknya pada tingkat sintaksis, untuk file header? Apakah ini masalah dengan kompiler?

Tidak. Extern "C" adalah untuk menghubungkan - khususnya kebijakan yang digunakan untuk nama simbol yang dihasilkan ("nama mangling") dan konvensi pemanggilan (perakitan apa yang akan dihasilkan untuk memanggil API dan menumpuk nilai parameter) - bukan kompilasi.

Masalah yang Anda hadapi tidak terbatas pada kata kunci this. Dalam basis kode kami saat ini, kami mem-porting beberapa kode ke C++ dan kami memiliki konstruksi seperti ini:

struct Something {
    char *value;
    char class[20]; // <-- bad bad code!
};

Ini berfungsi dengan baik dalam kode C, tetapi (seperti Anda) kami terpaksa mengganti nama agar dapat dikompilasi sebagai C++.

person utnapistim    schedule 03.09.2014
comment
Tip pro: Tulis kode yang kompatibel dengan nama C++ saat menulis perpustakaan C. Menghemat banyak sakit kepala bagi pengembang lain. - person Cole Johnson; 03.09.2014
comment
RE: masalah kelas Anda, perhatikan solusi hacky-belum-masih-mungkin-didukung-oleh-kompiler-Anda dalam jawaban saya. Tentu saja, jangan lakukan itu, perbaiki! :-) - person HostileFork says dont trust SE; 03.09.2014
comment
Oke, ini sudah jelas sekarang. Seperti yang Anda katakan, selesaikan masalah kata kunci ini melalui penggantian nama, ia mulai mengeluh dengan konversi int/bool, dan perbedaan bahasa inti C/C++ utama lainnya. Saya berpikir karena C eksternal akan dikompilasi menggunakan spesifikasi C, dan saya salah total. Terima kasih! - person nyarlathotep108; 03.09.2014
comment
@ColeJohnson: Itu biasanya saran bagus untuk header, saran buruk untuk implementasi. Anda ingin kode C cepat rusak dan rusak parah jika seseorang mencoba mengkompilasinya dengan kompiler C++. Memperkenalkan kesalahan halus karena bahasanya berbeda dengan semantik berbeda jauh lebih buruk. - person R.. GitHub STOP HELPING ICE; 03.09.2014
comment
@R.. Anda benar. Saya merujuk pada header. Saya hanya berpikir itu tersirat; Kurasa tidak. Implementasinya adalah hal yang sangat berbeda, saya setuju. - person Cole Johnson; 03.09.2014
comment
@R.. Er...Saya setuju dengan pendapat umum Anda bahwa jika ada area abu-abu yang kompatibel, Anda harus berusaha menghilangkannya secepat dan sekeras mungkin dalam kompilasi ulang. Tapi itu tidak ada hubungannya dengan programmer C yang secara aktif menamai bidang struct class dan variabel global this. - person HostileFork says dont trust SE; 04.09.2014

Anehnya, banyak kompiler tidak secara paksa melarang redefinisi kata kunci melalui praprosesor:

#include <iostream>

// temporary redefinition to compile code abusing the "this" keyword
#define cppThis this
#define this thisFunction

int this() {
    return 1020;
}

int that() {
   return this();
}

// put the C++ definition back so you can use it
#undef this
#define this cppThis

struct DumpThat {
    int dump() {
       std::cout << that();
    }
    DumpThat() {
       this->dump();
    }
};

int main ()
{
    DumpThat dt;
}

Jadi jika Anda menghadapi hambatan, itu memungkinkan Anda mengkompilasi file yang ditulis dengan asumsi C yang tidak dapat Anda ubah.

Namun, itu tidak akan memungkinkan Anda mendapatkan nama tautan "ini". Mungkin ada tautan yang memungkinkan Anda melakukan semacam pemetaan ulang nama untuk membantu menghindari tabrakan. Efek sampingnya mungkin adalah mereka mengizinkan Anda mengatakan thisFunction -> this, dan tidak memiliki masalah dengan sisi kanan pemetaan menjadi kata kunci.

Bagaimanapun...jawaban yang lebih baik jika Anda dapat mengubahnya adalah...ubahlah!

person HostileFork says dont trust SE    schedule 03.09.2014
comment
Menurut saya itu tidak aneh, atau kompiler punya pilihan. Langkah praprosesor ditentukan pada tingkat token. Pada tahap tersebut, token belum diurai menjadi kata kunci, jadi Anda tidak dapat menggunakan token kata kunci secara berbeda dari token non-kata kunci. - person MSalters; 03.09.2014
comment
@MSalters Lihat Definisi ulang kata kunci dalam C / C++...seseorang pasti dapat memasukkan kata-kata dari penggunaan praprosesor ke dalam daftar hitam. - person HostileFork says dont trust SE; 03.09.2014
comment
Aduh, benar - C hanya melarangnya di fase 7/8, setelah pra-pemrosesan fase 4 (lihat jawaban md5) tetapi di C++ langsung dilarang (sesuai pertanyaan tertaut). Tapi this tidak akan menjadi kata kunci di C. Jadi, alih-alih mendefinisikan ulang secara kondisional untuk C++, Anda harus mendefinisikan ulang secara kondisional untuk C. - person MSalters; 03.09.2014
comment
Ini adalah solusi bagus yang dapat menyelesaikan masalah kata kunci umum, tetapi sebenarnya ini tidak akan menyelesaikan semua perbedaan C/C++ secara umum. Sepertinya ada baiknya kita bisa mengedit file header, juga yang berasal dari perpustakaan eksternal. - person nyarlathotep108; 04.09.2014

Jika extern "C" mengizinkan Anda menggunakan kata kunci C++ sebagai simbol, kompiler harus menyelesaikannya di luar bagian extern "C". Misalnya:

extern "C" {
    int * this;  //global variable
    typedef int class;
}


int MyClass::MyFunction() { return *this; }  //what does this mean?
                                             //MyClass could have a cast operator
class MyOtherClass;  //forward declaration or a typedef'ed int?
person IronMensan    schedule 03.09.2014

Bisakah Anda lebih eksplisit tentang "menggunakan nama ini untuk beberapa variabel di salah satu file headernya"?

Apakah itu benar-benar sebuah variabel atau merupakan parameter dalam prototipe fungsi?

Jika yang terakhir, Anda tidak memiliki masalah nyata karena prototipe C (dan C++) mengidentifikasi parameter berdasarkan posisi (dan tipe) dan namanya bersifat opsional. Anda dapat memiliki versi prototipe yang berbeda, misalnya:

#ifdef __cplusplus
  extern "C" {
   void aFunc(int);
  }
#else
 void aFunc(int this);
#endif

Ingat tidak ada yang ajaib tentang file header - mereka hanya menyediakan kode yang disertakan secara leksikal di titik #include - seolah-olah Anda menyalin dan menempelkannya.

Jadi Anda bisa memiliki salinan header perpustakaan Anda sendiri yang melakukan trik seperti di atas, hanya menjadi masalah pemeliharaan untuk memastikan Anda melacak apa yang terjadi di header asli. Jika hal ini mungkin menjadi masalah, tambahkan skrip sebagai langkah pembuatan yang menjalankan perbedaan dengan aslinya dan pastikan satu-satunya titik perbedaan adalah kode solusi Anda.

person Andy Dent    schedule 03.09.2014