-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextern-c.html
581 lines (421 loc) · 42.5 KB
/
extern-c.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.0.0">
<meta name="baidu-site-verification" content="codeva-PBoQMHcqc8" />
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {"hostname":"lfeng.tech","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
</script>
<meta name="description" content="简述 extern “C”的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。">
<meta property="og:type" content="article">
<meta property="og:title" content="extern "c"解析">
<meta property="og:url" content="https://lfeng.tech/extern-c.html">
<meta property="og:site_name" content="Vincent's Notes">
<meta property="og:description" content="简述 extern “C”的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2015-07-21T21:23:15.000Z">
<meta property="article:modified_time" content="2015-11-15T13:28:18.000Z">
<meta property="article:author" content="Vincent">
<meta name="twitter:card" content="summary">
<link rel="canonical" href="https://lfeng.tech/extern-c.html">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome : false,
isPost : true,
lang : 'zh-CN'
};
</script>
<title>extern "c"解析 | Vincent's Notes</title>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<h1 class="site-title">Vincent's Notes</h1>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger">
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="main-menu menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>
</li>
</ul>
</nav>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content post posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://lfeng.tech/extern-c.html">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Vincent">
<meta itemprop="description" content="Vincent's tech blog">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Vincent's Notes">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
extern "c"解析
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2015-07-21 21:23:15" itemprop="dateCreated datePublished" datetime="2015-07-21T21:23:15Z">2015-07-21</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar-check"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2015-11-15 13:28:18" itemprop="dateModified" datetime="2015-11-15T13:28:18Z">2015-11-15</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/C/" itemprop="url" rel="index"><span itemprop="name">C++</span></a>
</span>
</span>
<span id="/extern-c.html" class="post-meta-item leancloud_visitors" data-flag-title="extern "c"解析" title="阅读次数">
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数:</span>
<span class="leancloud-visitors-count"></span>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-comment"></i>
</span>
<span class="post-meta-item-text">Valine:</span>
<a title="valine" href="/extern-c.html#valine-comments" itemprop="discussionUrl">
<span class="post-comments-count valine-comment-count" data-xid="/extern-c.html" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="简述"><a href="#简述" class="headerlink" title="简述"></a>简述</h1><blockquote>
<p>extern “C”的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。</p>
</blockquote>
<span id="more"></span>
<h1 id="extern-“c”-含义"><a href="#extern-“c”-含义" class="headerlink" title="extern “c” 含义"></a>extern “c” 含义</h1><h2 id="extern关键字"><a href="#extern关键字" class="headerlink" title="extern关键字"></a>extern关键字</h2><p><code>extern</code>是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。<br>通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在链接阶段中从模块A编译生成的目标代码中找到此函数。<br>与extern对应的关键字是<code>static</code>,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。</p>
<h2 id="编译链接形式"><a href="#编译链接形式" class="headerlink" title="编译链接形式"></a>编译链接形式</h2><p>作为一种面向对象的语言,<strong>C++支持函数重载,而过程式语言C则不支持</strong>。函数被C++编译后在符号库中的名字与C语言的不同。<br>例如,假设某个函数的原型为:<code>void foo( int x, int y );</code></p>
<ul>
<li>该函数被C编译器编译后在符号库中的名字为_foo</li>
<li>C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。 例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。<blockquote>
<p>C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以”.”来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。</p>
</blockquote>
</li>
</ul>
<h1 id="常见形式"><a href="#常见形式" class="headerlink" title="常见形式"></a>常见形式</h1><p>在用C++的项目源码中,经常会不可避免的会看到下面的代码:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __cplusplus</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> {</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"> </span><br><span class="line"><span class="comment">/*...*/</span></span><br><span class="line"> </span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __cplusplus</span></span><br><span class="line">}</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>
<ul>
<li>#ifdef/#endif、#ifndef/#endif用于条件编译,这里的作用就是<strong>避免重复包含头文件</strong></li>
<li>而#ifdef _cplusplus/#endif _cplusplus,就是用于在c++源文件中调用c源文件时,正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。</li>
</ul>
<h1 id="具体调用情形"><a href="#具体调用情形" class="headerlink" title="具体调用情形"></a>具体调用情形</h1><h2 id="C-调用C函数"><a href="#C-调用C函数" class="headerlink" title="C++调用C函数"></a>C++调用C函数</h2><p>使用<strong>extern ”c“</strong>在C++源文件中声明C函数,然后就可以直接从C或者C++函数中进行调用,示例如下:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">// C++ code</span><br><span class="line"> extern "C" void f(int); // one way</span><br><span class="line"> extern "C" { // another way</span><br><span class="line"> int g(double);</span><br><span class="line"> double h();</span><br><span class="line"> };</span><br><span class="line"> void code(int i, double d)</span><br><span class="line"> {</span><br><span class="line"> f(i);</span><br><span class="line"> int ii = g(d);</span><br><span class="line"> double dd = h();</span><br><span class="line"> // ...</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
<p>函数定义类似如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* C code: */</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> i)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">/* ... */</span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">g</span><span class="params">(<span class="keyword">double</span> d)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">/* ... */</span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">h</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">/* ... */</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<blockquote>
<p><strong>注意</strong>:由于使用了C语言的规范来进行编译,因此函数不支持重载,所以必须使用正确数目的变量</p>
</blockquote>
<h2 id="C调用C-函数"><a href="#C调用C-函数" class="headerlink" title="C调用C++函数"></a>C调用C++函数</h2><p>与上一种情况类似,使用<strong>extern ”c“</strong>在C++源文件中声明C++函数,然后就可以直接从C或者C++函数中进行调用,示例如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// C++ code:</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> <span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> i)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>函数<code>f()</code>可以按照下面方式使用:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* C code: */</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">cc</span><span class="params">(<span class="keyword">int</span> i)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">f</span>(i);</span><br><span class="line"> <span class="comment">/* ... */</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<blockquote>
<p>上面用法只适用于<strong>非成员函数</strong>,如果想从C语言调用成员函数,可以参考<a target="_blank" rel="noopener" href="https://isocpp.org/wiki/faq/mixing-c-and-cpp">mixing-c-and-cpp</a></p>
</blockquote>
<h2 id="C-包含标准C语言头文件"><a href="#C-包含标准C语言头文件" class="headerlink" title="C++包含标准C语言头文件"></a>C++包含标准C语言头文件</h2><ul>
<li><p>方式1:直接包含对应的C++封装好的头文件,此时无需其他操作</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// This is C++ code</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span> <span class="comment">// Nothing unusual in #include line</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> std::<span class="built_in">printf</span>(<span class="string">"Hello world\n"</span>); <span class="comment">// Nothing unusual in the call either</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li>
<li><p>方式2:使用C++编译器编译C文件,可以使用标准C语言的头文件和其中的函数</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* This is C code that I'm compiling using a C++ compiler */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span> <span class="comment">/* Nothing unusual in #include line */</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Hello world\n"</span>); <span class="comment">/* Nothing unusual in the call either */</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="C-包含非系统的C语言头文件"><a href="#C-包含非系统的C语言头文件" class="headerlink" title="C++包含非系统的C语言头文件"></a>C++包含非系统的C语言头文件</h2></li>
<li><p>方式1:使用<code>extern "C"</code>包含**#include所在行**,以此来告诉C++编译器该头文件中的函数是C语言函数</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// This is C++ code</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> {</span><br><span class="line"> <span class="comment">// Get declaration for f(int i, char c, float x)</span></span><br><span class="line"> <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"my-C-code.h"</span></span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">f</span>(<span class="number">7</span>, <span class="string">'x'</span>, <span class="number">3.14</span>); <span class="comment">// Note: nothing unusual in the call</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li>
<li><p>方式2:采用修改头文件的方式,将<code>extern "C" {...}</code>加到头文件中,方便C++用户#include该头文件到C++源代码中。但是由于标准C编译器无法识别<code>extern "C"</code>结构,因此必须使用<code>#ifdef</code>进行条件编译</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Step1:Put the following lines at the very top of your C header file (note: the symbol __cplusplus is #defined if/only-if the compiler is a C++ compiler):</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __cplusplus</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> {</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="comment">// Step2:Put the following lines at the very bottom of your C header file:</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __cplusplus</span></span><br><span class="line">}</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure></li>
<li><p>现在可以直接可以#include对应的头文件,而不需要添加<code>extern "C"</code>到C++源文件</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// This is C++ code</span></span><br><span class="line"><span class="comment">// Get declaration for f(int i, char c, float x)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"my-C-code.h"</span> <span class="comment">// Note: nothing unusual in #include line</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">f</span>(<span class="number">7</span>, <span class="string">'x'</span>, <span class="number">3.14</span>); <span class="comment">// Note: nothing unusual in the call</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="C-调用非系统的C函数"><a href="#C-调用非系统的C函数" class="headerlink" title="C++调用非系统的C函数"></a>C++调用非系统的C函数</h2></li>
</ul>
<p>如果想要调用一个单独的C函数,但是不想<code>#include</code>声明该函数的<code>.h</code>文件,可以在C++源文件中使用<code>extern "C"</code>语法,但是注意该C函数需要使用全部的函数原型,示例如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> <span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> i, <span class="keyword">char</span> c, <span class="keyword">float</span> x)</span></span>;</span><br></pre></td></tr></table></figure>
<p>如果有多个C函数,可以使用<code>{}</code>包含几个函数原型,如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> {</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> i, <span class="keyword">char</span> c, <span class="keyword">float</span> x)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">g</span><span class="params">(<span class="keyword">char</span>* s, <span class="keyword">const</span> <span class="keyword">char</span>* s2)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">double</span> <span class="title">sqrtOfSumOfSquares</span><span class="params">(<span class="keyword">double</span> a, <span class="keyword">double</span> b)</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>之后可以直接像C++函数一样调用该C函数:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">f</span>(<span class="number">7</span>, <span class="string">'x'</span>, <span class="number">3.14</span>); <span class="comment">// Note: nothing unusual in the call</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="C调用C-函数-1"><a href="#C调用C-函数-1" class="headerlink" title="C调用C++函数"></a>C调用C++函数</h2><p>直接用<code>extern "C"</code>告诉编译器该函数会被一个C编译器调用</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// This is C++ code</span></span><br><span class="line"><span class="comment">// Declare f(int,char,float) using extern "C":</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> <span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> i, <span class="keyword">char</span> c, <span class="keyword">float</span> x)</span></span>;</span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"><span class="comment">// Define f(int,char,float) in some C++ module:</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> i, <span class="keyword">char</span> c, <span class="keyword">float</span> x)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<hr>
<blockquote>
<p><strong>注意:</strong>如果没有正确使用<code>extern "C"</code>,往往不会出现编译错误,而是链接错误,因为C++编译器为了支持重载,会把函数名进行转换,而C编译器不会。</p>
</blockquote>
<hr>
<p><strong>参考链接:</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://isocpp.org/wiki/faq/mixing-c-and-cpp">How to mix C and C++</a></li>
<li><a target="_blank" rel="noopener" href="http://www.jianshu.com/p/5d2eeeb93590">extern “c”用法解析</a></li>
<li><a target="_blank" rel="noopener" href="http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html">C++项目中的extern “C” {}</a></li>
</ul>
</div>
<div>
<ul class="post-copyright">
<li class="post-copyright-author">
<strong>本文作者: </strong>Vincent
</li>
<li class="post-copyright-link">
<strong>本文链接:</strong>
<a href="https://lfeng.tech/extern-c.html" title="extern "c"解析">https://lfeng.tech/extern-c.html</a>
</li>
<li class="post-copyright-license">
<strong>版权声明: </strong>本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处!
</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-nav">
<div class="post-nav-item">
<a href="/heap-and-stack.html" rel="prev" title="堆和栈">
<i class="fa fa-chevron-left"></i> 堆和栈
</a></div>
<div class="post-nav-item">
<a href="/Check-Series-Update-by-Python.html" rel="next" title="美剧更新提醒 by Python">
美剧更新提醒 by Python <i class="fa fa-chevron-right"></i>
</a></div>
</div>
</footer>
</article>
</div>
<div class="comments" id="valine-comments"></div>
<script>
window.addEventListener('tabs:register', () => {
let { activeClass } = CONFIG.comments;
if (CONFIG.comments.storage) {
activeClass = localStorage.getItem('comments_active') || activeClass;
}
if (activeClass) {
let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
if (activeTab) {
activeTab.click();
}
}
});
if (CONFIG.comments.storage) {
window.addEventListener('tabs:click', event => {
if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
let commentClass = event.target.classList[1];
localStorage.setItem('comments_active', commentClass);
});
}
</script>
</div>
<div class="toggle sidebar-toggle">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
<aside class="sidebar">
<div class="sidebar-inner">
<ul class="sidebar-nav motion-element">
<li class="sidebar-nav-toc">
文章目录
</li>
<li class="sidebar-nav-overview">
站点概览
</li>
</ul>
<!--noindex-->
<div class="post-toc-wrap sidebar-panel">
<div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AE%80%E8%BF%B0"><span class="nav-number">1.</span> <span class="nav-text">简述</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#extern-%E2%80%9Cc%E2%80%9D-%E5%90%AB%E4%B9%89"><span class="nav-number">2.</span> <span class="nav-text">extern “c” 含义</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#extern%E5%85%B3%E9%94%AE%E5%AD%97"><span class="nav-number">2.1.</span> <span class="nav-text">extern关键字</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BC%96%E8%AF%91%E9%93%BE%E6%8E%A5%E5%BD%A2%E5%BC%8F"><span class="nav-number">2.2.</span> <span class="nav-text">编译链接形式</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%B8%B8%E8%A7%81%E5%BD%A2%E5%BC%8F"><span class="nav-number">3.</span> <span class="nav-text">常见形式</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%B7%E4%BD%93%E8%B0%83%E7%94%A8%E6%83%85%E5%BD%A2"><span class="nav-number">4.</span> <span class="nav-text">具体调用情形</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#C-%E8%B0%83%E7%94%A8C%E5%87%BD%E6%95%B0"><span class="nav-number">4.1.</span> <span class="nav-text">C++调用C函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#C%E8%B0%83%E7%94%A8C-%E5%87%BD%E6%95%B0"><span class="nav-number">4.2.</span> <span class="nav-text">C调用C++函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#C-%E5%8C%85%E5%90%AB%E6%A0%87%E5%87%86C%E8%AF%AD%E8%A8%80%E5%A4%B4%E6%96%87%E4%BB%B6"><span class="nav-number">4.3.</span> <span class="nav-text">C++包含标准C语言头文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#C-%E5%8C%85%E5%90%AB%E9%9D%9E%E7%B3%BB%E7%BB%9F%E7%9A%84C%E8%AF%AD%E8%A8%80%E5%A4%B4%E6%96%87%E4%BB%B6"><span class="nav-number">4.4.</span> <span class="nav-text">C++包含非系统的C语言头文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#C-%E8%B0%83%E7%94%A8%E9%9D%9E%E7%B3%BB%E7%BB%9F%E7%9A%84C%E5%87%BD%E6%95%B0"><span class="nav-number">4.5.</span> <span class="nav-text">C++调用非系统的C函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#C%E8%B0%83%E7%94%A8C-%E5%87%BD%E6%95%B0-1"><span class="nav-number">4.6.</span> <span class="nav-text">C调用C++函数</span></a></li></ol></li></ol></div>
</div>
<!--/noindex-->
<div class="site-overview-wrap sidebar-panel">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image" alt="Vincent"
src="/images/avatar.jpg">
<p class="site-author-name" itemprop="name">Vincent</p>
<div class="site-description" itemprop="description">Vincent's tech blog</div>
</div>
<div class="site-state-wrap motion-element">
<nav class="site-state">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">65</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-categories">
<a href="/categories/">
<span class="site-state-item-count">15</span>
<span class="site-state-item-name">分类</span></a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/">
<span class="site-state-item-count">23</span>
<span class="site-state-item-name">标签</span></a>
</div>
</nav>
</div>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/teckee" title="GitHub → https://github.com/teckee" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
</span>
<span class="links-of-author-item">
<a href="mailto:h0ck@foxmail.com" title="E-Mail → mailto:h0ck@foxmail.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
</span>
</div>
</div>
</div>
</aside>
<div id="sidebar-dimmer"></div>
</div>
</main>
<footer class="footer">
<div class="footer-inner">
<div class="beian"><a href="https://beian.miit.gov.cn/" rel="noopener" target="_blank">沪ICP备19042895号-2 </a>
</div>
<div class="copyright">
©
<span itemprop="copyrightYear">2023</span>
<span class="with-love">
<i class="fa fa-heart"></i>
</span>
<span class="author" itemprop="copyrightHolder">Vincent</span>
</div>
<div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
</div>
<div class="busuanzi-count">
<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
<span class="post-meta-item-icon">
<i class="fa fa-user"></i>
</span>
<span class="site-uv" title="总访客量">
<span id="busuanzi_value_site_uv"></span>
</span>
</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="site-pv" title="总访问量">
<span id="busuanzi_value_site_pv"></span>
</span>
</span>
</div>
</div>
</footer>
</div>
<script src="/lib/anime.min.js"></script>
<script src="/lib/velocity/velocity.min.js"></script>
<script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script>
<script src="/js/motion.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>
<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
var GUEST = ['nick', 'mail', 'link'];
var guest = 'nick,mail,link';
guest = guest.split(',').filter(item => {
return GUEST.includes(item);
});
new Valine({
el : '#valine-comments',
verify : false,
notify : false,
appId : 'cgQ905Fj6xbazWtyi9b1hafr-gzGzoHsz',
appKey : '68EFTwnd9XYY352gRUJlJyMu',
placeholder: "Just go go",
avatar : 'mm',
meta : guest,
pageSize : '10' || 10,
visitor : true,
lang : '' || 'zh-cn',
path : location.pathname,
recordIP : false,
serverURLs : ''
});
}, window.Valine);
});
</script>
</body>
</html>