C# 关键字extern用法

修饰符用于声明在外部实现的方法。extern 修饰符的常见用法是在使用 Interop 服务调入非

托管代码时与 DllImport 属性一起使用;在这种情况下,该方法还必须声明为 static,如下面的示例所示:[DllImport("avifil32.dll")]
private static extern void AVIFileInit();

注意 
extern 关键字还可以定义外部程序集别名,使得可以从单个程序集中引用同一组件的不同版本。

将 abstract(C# 参考)和 extern 修饰符一起使用来修改同一成员是错误的。使用 extern 修饰符意味着方法在 C# 代码的外部实现,而使

用 abstract 修饰符意味着在类中未提供方法实现。注意 
extern 关键字在使用上比在 C++ 中有更多的限制。若要与 C++ 关键字进行比较,请参见 C++ Language Reference 中的 Using extern to

Specify Linkage。

在该示例中,程序接收来自用户的字符串并将该字符串显示在消息框中。程序使用从 User32.dll 库导入的 MessageBox 方法。

using System;
using System.Runtime.InteropServices;
class MainClass
{
  [DllImport("User32.dll")]
  public static extern int MessageBox(int h, string m, string c, int type);
  //hovertree.com
  static int Main()
  {
      string myString;
      Console.Write("Enter your message: ");
      myString = Console.ReadLine();
      return MessageBox(0, myString, "My Message Box", 0);
  }
}

此示例使用 C 程序创建一个 DLL,在下一示例中将从 C# 程序调用该 DLL。

[cpp] 

// cmdll.c   何问起
// compile with: /LD
int __declspec(dllexport) SampleMethod(int i)
{
  return i*10;
} 

该示例使用两个文件 CM.cs 和 Cmdll.c 来说明 extern。C 文件是示例 2 中创建的外部 DLL,它从 C# 程序内调用。

[c-sharp]

// cm.cs
using System;
using System.Runtime.InteropServices;
public class MainClass
{
  [DllImport("Cmdll.dll")]
  public static extern int SampleMethod(int x);
  //hovertree.com
  static void Main()
  {
      Console.WriteLine("SampleMethod() returns {0}.", SampleMethod(5));
  }
} 

输出

SampleMethod() returns 50.
生成项目:
使用 Visual C++ 命令行将 Cmdll.c 编译为 DLL:cl /LD Cmdll.c使用命令行编译 CM.cs:csc CM.cs这将创建可执行文件 CM.exe。运行此程

序时,SampleMethod 将值 5 传递到 DLL 文件,该文件将此值乘以 10 返回extern "C"
  extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

  (1) 被extern "C"限定的函数或变量是extern类型的;

  extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:

  extern int a;

  仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

  通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。

实例:

[cpp]

//cppExample.h  

#ifndef MODULE_A_H
#define MODULE_A_H
extern int foo( int x, int y );// 声明函数,其为extern类型
#endif  

//////////////////////////////////////////////////////////////////////////////////////////////
  //hovertree.com

//////////////////////////////////////////////////////////////////////////////////////////////  

//cppExample.cpp  

#include <iostream>
#include "cppExample.h"
using namespace std;  

int foo( int x, int y )//定义extern类型的函数
{
cout << x+y;
return 0;
}  

////////////////////////////////////////////////////////////////////////////////////////////////////  

//main.cpp  

#include <iostream>
#include"cppExample.h"
using namespace std;  

void main()
{
foo(5,6);//函数调用
}  

/////////////////////////////////////////////////////////////////////////////////////////////////////

这里呢,就有了个疑问:其实如果再cppExample.h中声明了一个全局函数int foo(Int x, int y),然后在main.cpp中调用foo函数,其都是一样的,都可以成功编译,函数成功调用,那这个extern到底有什么用呢,不是多此一举么?(暂放,以后补充)

与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

(2) 被extern "C"修饰的变量和函数是按照C语言方式编译和连接的;
  未加extern “C”声明时的编译方式
  首先看看C++中对类似C的函数是怎样编译的。

  作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

  void foo( int x, int y );

  该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangledname”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y)编译生成的符号是不相同的,后者为_foo_int_float。

  同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

  未加extern "C"声明时的连接方式
  假设在C++中,模块A的头文件如下:

[cpp]

// 模块A头文件 moduleA.h  

  #ifndef MODULE_A_H
  #define MODULE_A_H
  int foo( int x, int y );
  #endif  

  在模块B中引用该函数:  

  // 模块B实现文件 moduleB.cpp
  #include "moduleA.h"
  foo(2,3);
//hovertree.com

  

  实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!
  加extern "C"声明后的编译和连接方式
  加extern "C"声明后,模块A的头文件变为:

  

[cpp]

// 模块A头文件 moduleA.h  

  #ifndef MODULE_A_H
  #define MODULE_A_H
  extern "C" int foo( int x, int y );
  #endif
//hovertree.com

  在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

  (1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

  (2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

  如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。

  所以,可以用一句话概括extern“C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):

二. extern "C"的惯用法

  (1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:
  

[cpp] 

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

  而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下:

[cpp]

/* c语言头文件:cExample.h */  

  #ifndef C_EXAMPLE_H
  #define C_EXAMPLE_H
  extern int add(int x,int y);
  #endif  

  /* c语言实现文件:cExample.c */  

  #include "cExample.h"
  int add( int x, int y )
  {
  return x + y;
  }  

  // c++实现文件,调用add:cppFile.cpp
  //以下这段可以替换成 extern "C" int foo(int x, int y);  

    extern "C"
    {
  #include "cExample.c"
  }  

    //替换结束  hovertree.com

  int main(int argc, char* argv[])
  {
  add(2,3);
  return 0;
  }  

    如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。

(2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

  笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下:

[cpp]

//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif  

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

//C++实现文件 cppExample.cpp
#include <stdio.h>
#include "cppHeader.h"
int add( int x, int y )
{
return x + y;
}  

//----------------------------------------------------------
#include<stdio.h>
/* C实现文件 cFile.c
/* 这样会编译出错:#include "cExample.h"  */
extern int add( int x, int y );  

int main()
{
int a = add(2,3);
return 0;
}
//hovertree.com

转自:http://hovertree.com/h/bjaf/1iogox2j.htm

http://www.cnblogs.com/sosoft/p/timu.html

时间: 2024-10-02 22:37:56

C# 关键字extern用法的相关文章

关于c语言中关键字extern用法。

看c语言的ppt看到extern中的生命外部变量,懵逼了.然后在网上查了关于extern的用法.都不是我想要的. 找了半个小时,又写写程序,算是明白了. extern声明外部变量时候,也就是在别的函数里面,一个文件已经有了外部变量,int A=13,B=0:当我别的函数想用这个A,B变量的值得时候, 可以在函数里面用extern声明即:extern A,B:我觉得也就是扩展的意思,有点类似java中继承的味道(楼主java半路转了啊,尴尬.). 测试代码如下: #include<stdio.h>

C语言中extern关键字的用法

转载请注明出处http://blog.csdn.net/xingjiarong/article/details/47614171 利用关键字extern,可以在一个文件中引用另一个文件中定义的变量或者函数,下面就结合具体的实例,分类说明一下. 一.引用同一个文件中的变量 #include<stdio.h> int func(); int main() { func(); //1 printf("%d",num); //2 return 0; } int num = 3; i

const 和 extern 用法小結

 雖說不難,但很重要!! 1.       const常量,如const int max = 100;  优点:const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应) 2.       const 修饰类的数据成员.如:class A { const int size; … } const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的.因为类可以创建多个对象,

extern用法

Extern用法 用例子给你示范 // 1.cpp int x = 10; // 2.cpp 注意没有包含1.cpp #include <iostream> using namespace std; extern int x; int main () { cout << x << endl; } //则输出10 两个文件同在一个项目(project)中,你不包含某个文件(cpp)而可以用它内部定义的变量,(里是.pp不是.h, 因为在.h中定义的数据不能在.cpp中用除

【C/C++】关键字extern

extern关键字的含义是什么? extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用. extern关键字的一般用法是怎样的? 在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明. 例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可.这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错:它会在link阶段时从模

c和c++精炼总结(重点是几个重要的关键字的用法)

1.cin输入多个数据用空格或者回车来区分,不可以用“,”来区分. 2.多个判断语句下,if...if...else;这样写程序会导致最后两个形成独立判断,也就是说,如果第一个if成立,那么除了执行第一个if下的内容,还会执行else下的内容:为了避免这样的问题,就需要用if...else if...else这样的嵌套 3.随机数函数的应用 (1)srand(time(0))和rand():前者是为产生随机数提供种子函数,后者就是随机值产生的函数:而套用的time(0),目的是为了    产生随

super关键字的用法

package com.frank;//定义包名,必须是第一行.如果没有包名,那么就会被放在一个没有名字的默认包中. import java.util.*; /** 继承 */ public class Sample {     public static void main(String[] args)     {         OldMan o = new OldMan("张三",80);         System.out.println("名字:"+o.

【转载】理解C语言中的关键字extern

原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻译了一下.(原文:http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/)   我确定这篇文章对c语言的初学者会有很大的帮助,因为这将使他们更好更熟练的使用c语言.所以就让我先来说说extern关键字在变量和函数上的应用.最基本

.Net 基础new关键字的用法

一.new的基本功能 一般说来,new关键字在.net中用于以下四个场合. 作为运算符,用于创建对象和调用构造函数,范围用得最多吧. 实现多态. 作为修饰符,用于向基类成员隐藏继承类成员,一般继承情况下,扩展基类方法用得多. 作为泛型参数约束,用于在泛型声明中约束用作类型参数的参数类型,这个也好像用得多吧. 二.new的基本用法 先来说说作为泛型参数约束的用法. MSDN 中的定义是:new约束指定泛型类声明中的任何类型参数都必须有公共的无参构造函数.当泛型类型创建类型的新实例时,将此约束应用于