সি ++ কোড থেকে একটি সি ফাংশন কল করুন


90

আমার একটি সি ফাংশন রয়েছে যা আমি সি ++ থেকে কল করতে চাই। আমি " extern "C" void foo()" ধরণের পদ্ধতির ব্যবহার করতে পারিনি কারণ সি ফাংশনটি g ++ ব্যবহার করে সংকলন করতে ব্যর্থ হয়েছিল। তবে এটি জিসিসি ব্যবহার করে সূক্ষ্ম সংকলন করে। কোনও ধারণা কীভাবে সি ++ থেকে ফাংশনটি কল করবেন?


4
আপনি দয়া করে কিছু উদাহরণ কোড এবং g++ত্রুটি বার্তাগুলি লিখতে পারেন
ম্যাথিউ রাউজেট

7
আপনি যদি এটি C ++ সংকলক দিয়ে সংকলন করেন তবে এটি সি ++। সি কোডটি কোনও সি ++ সংকলক দিয়ে সংকলন করতে হবে না। তারা বিভিন্ন ভাষা। আপনার কোডটি বৈধ সি ++ নয় এবং এর জন্য কোনও সি ++ সংকলক দিয়ে সংকলন করে না।
xaxxon

4
@ ম্যাথিউরউজেটvoid valid_in_C_but_not_in_CPlusPlus(size_t size) { char variable_length_array[size]; }
অটিস্টিক

4
আমার চেষ্টা: void f(void *pv) { int *pi = pv; *pi = 42; }^^
gx_

4
এটি খোলা রেখে দেওয়া উচিত, বিশেষত এটির উত্তম উত্তর রয়েছে যা সি কোডের জন্য সি (সি ++ এর চেয়ে) সংকলক কীভাবে ব্যবহার করতে পারে তা নির্দেশ করে।
ক্রিস স্ট্রাটন

উত্তর:


126

সি কোডটি এভাবে সংকলন করুন:

gcc -c -o somecode.o somecode.c

তারপরে সি ++ কোডটি এর মতো:

g++ -c -o othercode.o othercode.cpp

তারপরে এগুলিকে সি ++ লিঙ্কারের সাথে লিঙ্ক করুন:

g++ -o yourprogram somecode.o othercode.o

আপনি সি ফাংশনের জন্য ঘোষণার অন্তর্ভুক্ত করার সময় আপনাকে সি ++ সংকলকটিও বলতে হবে যে একটি সি শিরোনাম আসছে। তাই দিয়ে othercode.cppশুরু:

extern "C" {
#include "somecode.h"
}

somecode.h এর মতো কিছু থাকা উচিত:

 #ifndef SOMECODE_H_
 #define SOMECODE_H_

 void foo();

 #endif


(আমি এই উদাহরণে জিসিসি ব্যবহার করেছি, তবে যে কোনও সংকলকের ক্ষেত্রে নীতিটি সমান। যথাক্রমে সি এবং সি ++ হিসাবে আলাদাভাবে তৈরি করুন, তারপরে একে একে সংযুক্ত করুন))


7
@ অর্ন ভাল পয়েন্ট কিছু লোকেরা শিরোনামের সাথে শিরোনামটি মোড়ানো রেখে তাদের সিতে কিছু সি ++ extern "C"করে #ifdef __cplusplus
বিনোদন

@ আরনে নীচে আমার উত্তর দেখুন। আনইন্ডাইন্ড হিসাবে আপনি দেখতে পাচ্ছেন যে আমি তাদের মধ্যে একজন;)
gx_

4
তোমাকে অনেক ধন্যবাদ ! এটি আমার জন্য খুব দরকারী ছিল :)
হেশাম এরাকী

আমি নিম্নলিখিত ত্রুটিটি পেয়েছিলাম: ত্রুটি: # 337: লিঙ্কেজ স্পেসিফিকেশনটি পূর্ববর্তী "foo" (লাইন 1 এ ঘোষিত) সাথে সামঞ্জস্যপূর্ণ নয় এখন এটি সংকলন ঠিক আছে। কেউ কি ব্যাখ্যা করতে পারেন?
ফয়জানহুসাইন রব্বানী

@ ফাইজান রাব্বানী, আরও অনেক বিস্তারিত ছাড়াই নয়।
অধ্যাপক ফ্যালকেন

61

পরিষ্কারভাবে বিচ্ছিন্ন সি এবং সি ++ কোড সহ একটি উদাহরণ দেওয়ার জন্য আমাকে অন্যান্য উত্তর এবং মন্তব্যগুলি থেকে বিট এবং টুকরো সংগ্রহ করতে দিন:

সি অংশ:

foo.h :

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"

void foo(void)
{
    /* ... */
}

সঙ্গে এই কম্পাইল gcc -c -o foo.o foo.c

সি ++ অংশ:

বার.cpp

extern "C" {
  #include "foo.h" //a C header, so wrap it in extern "C" 
}

void bar() {
  foo();
}

এটি দিয়ে সংকলন করুন g++ -c -o bar.o bar.cpp

এবং তারপরে এগুলি সমস্ত লিঙ্ক করুন:

g++ -o myfoobar foo.o bar.o

যুক্তি: সি কোডটি সরল সি কোড হওয়া উচিত, #ifdef"সম্ভবত কোনও দিন আমি অন্য ভাষা থেকে এটি কল করব" এর জন্য কোনও এস। যদি কিছু সি ++ প্রোগ্রামার আপনার সি ফাংশনগুলিকে কল করে তবে এটি তাদের সমস্যা কীভাবে এটি করবেন, আপনার নয়। এবং যদি আপনি সি ++ প্রোগ্রামার হন তবে সি শিরোনামটি আপনার নাও হতে পারে এবং আপনার এটি পরিবর্তন করা উচিত নয়, সুতরাং আপনার অবিচ্ছিন্ন ফাংশন নামগুলি পরিচালনা করা (অর্থাত্ extern "C") আপনার সি ++ কোডের সাথে সম্পর্কিত।

আপনি অবশ্যই অবশ্যই নিজেকে একটি সুবিধার্থে সি ++ শিরোনাম লিখতে পারেন যা extern "C"ঘোষণাপত্রে সি শিরোনাম মোড়ানো ছাড়া কিছুই করে না ।


7
বৈধ মনে হয়। যৌক্তিকতার জন্য +1
gx_

অবশেষে এর সম্পূর্ণ পরিষ্কার ব্যাখ্যা। অসংখ্য ধন্যবাদ!
ড্যানিয়েল সাউটার

16

আমি অধ্যাপক ফ্যালকেনের উত্তরের সাথে একমত , তবে আর্নে মের্টজের মন্তব্যের পরে আমি একটি সম্পূর্ণ উদাহরণ দিতে চাই (সবচেয়ে গুরুত্বপূর্ণ অংশটি হ'ল #ifdef __cplusplus):

somecode.h

#ifndef H_SOMECODE
#define H_SOMECODE

#ifdef __cplusplus
extern "C" {
#endif

void foo(void);

#ifdef __cplusplus
}
#endif

#endif /* H_SOMECODE */

somecode.c

#include "somecode.h"

void foo(void)
{
    /* ... */
}

othercode.hpp

#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE

void bar();

#endif /* HPP_OTHERCODE */

othercode.cpp

#include "othercode.hpp"
#include "somecode.h"

void bar()
{
    foo(); // call C function
    // ...
}

তারপরে আপনি সংকলন এবং লিঙ্ক করার জন্য অধ্যাপক ফ্যালকেনের নির্দেশাবলী অনুসরণ করুন।

এটি কাজ করে কারণ সংকলন করার সময় gcc, ম্যাক্রো __cplusplusসংজ্ঞায়িত করা হয় নি, সুতরাং এতে somecode.hঅন্তর্ভুক্ত somecode.cশিরোনামটি প্রাক প্রসেসিংয়ের পরে এর মতো:

void foo(void);

এবং যখন সঙ্গে সংকলন g++, তারপর __cplusplus হয় সংজ্ঞায়িত, এবং তাই হেডারের মধ্যে অন্তর্ভুক্ত othercode.cppএখন দেখতে যে:

extern "C" {

void foo(void);

}

4
thb, আমি #ifdef __cplusplusসি কোডটি পছন্দ করি না । সি কোডটি নিম্ন স্তর এবং এটি কোনও দিন সি ++ কোড থেকে কল করা যেতে পারে কিনা তা বিরক্ত করার দরকার নেই। ইমো যার #ifdefব্যবহার কেবলমাত্র সি ++ কোডে রয়েছে যদি আপনি সি ++ তে লিখিত একটি লাইব্রেরির জন্য সি বাইন্ডিং শিরোনাম সরবরাহ করতে চান তবে অন্যভাবে নয়।
আরনে মের্টজ

4
@ অধ্যাপক অবশ্যই, তবে এটি একটি সংজ্ঞায়িত যা সি কোডের জন্য নয়, সি ++ কোডের "নিম্নগামী" সামঞ্জস্যতা সরবরাহ করতে সক্ষম হবে provide
আরনে মের্টজ

1

এই উত্তরটি এমন একটি ক্ষেত্রে অনুপ্রাণিত হয়েছিল যেখানে অ্যানির যুক্তি সঠিক ছিল। একজন বিক্রেতা এমন একটি লাইব্রেরি লিখেছিলেন যা একবার সি এবং সি ++ উভয়কেই সমর্থন করেছিল; যাইহোক, সর্বশেষতম সংস্করণটি কেবল সিটিকে সমর্থন করেছে নিম্নলিখিত কোডগুলিতে থাকা অনুসন্ধান সংক্রান্ত নির্দেশাবলী বিভ্রান্তিকর ছিল:

#ifdef __cplusplus
extern "C" {
#endif

সি ++ এ সংকলনের চেষ্টা করে আমার বেশ কয়েক ঘন্টা ব্যয় করেছে। কেবল সি ++ থেকে সি কল করা আরও সহজ ছিল।

Ifdef __cplusplus কনভেনশন একক দায়িত্বের নীতি লঙ্ঘন করছে। এই সম্মেলনটি ব্যবহার করে একটি কোড একবারে দুটি জিনিস করার চেষ্টা করছে:

  • (1) সিতে একটি ফাংশন সম্পাদন করুন - এবং -
  • (২) সি ++ এ একই ফাংশনটি সম্পাদন করুন

এটি একইসাথে আমেরিকান এবং ব্রিটিশ উভয় ইংরেজিতে লেখার চেষ্টা করার মতো। এটি অযথা অবিচ্ছিন্নভাবে একটি # আইডিডিএফ __থেকেনসিভ স্প্যানার # বেল্ট __কয়েনকেন্জলিশ রেঞ্চ একটি অপব্যবহারের সরঞ্জামের মতো নিক্ষেপ করছে যা কোডটিতে # এন্ডিফ পড়তে কোডকে আরও শক্ত করে তোলে।

সাধারণ কোড এবং ছোট গ্রন্থাগারগুলির জন্য ifdef __cplusplus কনভেনশন কাজ করতে পারে; তবে জটিল লাইব্রেরিগুলির জন্য একটি ভাষা বা অন্যটি বেছে নেওয়া এবং এটির সাথে থাকা ভাল। কোনও একটিকে সমর্থন করা উভয়কে সমর্থন করার চেয়ে কম রক্ষণাবেক্ষণ করবে।

এটি উবুন্টু লিনাক্সে সংকলন করার জন্য আর্নের কোডে আমি যে পরিবর্তন করেছি সেগুলির রেকর্ড এটি।

foo.h :

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"
#include <stdio.h>

void foo(void)
{
     // modified to verify the code was called
     printf("This Hello World was called in C++ and written in C\n");
}

বার.cpp

extern "C" {
    #include "foo.h" //a C header, so wrap it in extern "C" 
}

int main() {
  foo();
  return(0);
}

মেকফিল

# -*- MakeFile -*-
# dont forget to use tabs, not spaces for indents
# to use simple copy this file in the same directory and type 'make'

myfoobar: bar.o foo.o
    g++ -o myfoobar foo.o bar.o 

bar.o: bar.cpp
    g++ -c -o bar.o bar.cpp

foo.o: foo.c
    gcc -c -o foo.o foo.c
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.