请问一下vc++2010vc如何调用自己写的函数库服务端一定要有一个公网ip吗

若该文为原创文章未经允许不嘚转载
各位读者,知识无穷而人力有穷要么改需求,要么找专业人士要么自己研究

点击确认后,开始向导创建工程如下图:

点击“確认”,工程目录如下图:

创建库源码,并生成C库

C库头文件添加(回调函数的全局变量指针和设置回调函数的函数)

解决被调用时可能無法查看到printf打印信息

设置依赖项为了每次运行该测试应用之前,先编译生成对应的dll方式dll修改未更新,如下图:

运行时出现如下报错調用不带输入参数的不报错,输入参数的签名对不上(就是函数定义);

此时我们修改c#调用方式如下图:

在C#中若出现直接挂掉(当前项目中,若当机无异常或者无已停止运行目前所知都是调用的C库挂掉的,从C库找原因)特别注意委托函数需要加上调用的方式,是Cdecl不是StdDecl如下图:

  1. CallingConvention.Cdecl:C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈对于传送参数的内存栈是由调用者来維护的(正因为如此,实现可变参数的函数只能使用该调用约定)另外,在函数名修饰约定方面也有所不同_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式VC将函数编譯后会在函数名前面加上下划线前缀,是MFC缺省调用约定;
  2. CallingConvention.StdDecl:__stdcall调用约定相当于16位动态库中经常使用的PASCAL调用约定在32位的VC++5.0中PASCAL调用约定不再被支歭(实际上它已被定义为__stdcall。除了__pascal外__fortran和__syscall也不被支持),取而代之的是__stdcall调用约定两者实质上是一致的,即函数的参数自右向左通过栈传递被调用的函数在返回前清理传送参数的内存栈但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)_stdcall是Pascal的缺省調用方式,通常用于Win32Api中函数采用从右到左的压栈方式,自己在退出时清空堆栈VC将函数编译后会在函数名前面加上下划线前缀,在函数洺后加上"@"和参数的字节数;

解决被调用时可能无法查看到printf打印信息

需要重定向输出使用setbuf函数,如下图:

不能在运行时每次调用,所以峩们优化一下定义一个初始化函数,修改库的头文件和源文件如下:

半年没有写东西了也就出差了半年。半年没有用C#写了半年VC,呵呵。有时候其实有挺多东西vc如何调用自己写的函数库不过一忙起来人就懒了。简单的东西不想写复杂嘚又写不了,哈哈最近不是太忙,大概看了下COM组件模型然后对DLL工作,库文件有了一些兴趣因为工作和自己vc如何调用自己写的函数库程序可以延伸到这些知识上,所以对DLL进行了一定的了解而且对于直接开始编写C#应用程序的人来说,也很少会去了解这些所以决定写下來。

库文件是我们在接触编程时经常听到的词那么什么是库文件。其实库文件是一种重用的思想比如我们自己编写C#的程序,可能会把公用的一些方法放在一个名为Common的项目中然后编译成DLL,其他项目引用这个程序集就可以调用这个里面的方法,而不用自己去实现在说嘚大一点,.NET中提供给我们使用的类也是存放在.NET库中的。而整个WINDOWS系统都是建立在库文件基础上的。

其实在最初的时候是没有库文件的概念所有功能都是自己实现的。为了提高效率减少重复工作,就必须对代码重用重用方法有很对,比如对于一些通用的方法的实现代碼让编译器自己生成但这个问题是,一旦方法变更会添加编译器也必须修改了。另一个方法是把常用的方法编译成.obj模块文件这样在編译的时候,去链接这些模块文件就能实现代码重用。但是所有方法放到一个obj文件中文件会很庞大,占用内存;如果为每个方法提供┅个obj文件那又会相当的麻烦。

于是就出现了静态库(static library)静态库是一个或多个.obj文件的集合。使用到这些.obj文件对应的函数时只需要在连接时提供该静态库,而不需要列举用到的.obj文件而连接器进行连接的时候,只会将程序中用到的函数对应的.obj文件连接到程序中静态库的形式就是我们WINDOWS上常见的.lib文件。

但静态库的确定是每个程序使用时都会吧需要的obj文件拷贝到内存中,100个程序就有100个拷贝这样对内存的浪費很大,而且如果静态库文件更新的话程序也需要重新编译,进行连接于是共享库(shared library,也叫做动态连接库)就出现了首先他是被加載到公用的内存空间中,是所有程序共享的所以对节省了内存;另外他在编译时没有象静态库那样,把代码直接连接到了程序中只是插入了动态库的一些信息,供调用时使用这样,我们就有可能直接修改动态库而不需要重新编译程序。

是指当多个应用程序共享一个DLL戓COM组件时所引发的一系列问题比如一个应用程序安装一个新版本DLL,而该DLL与机器上的现有版本不向后兼容这样就可能导致以前的引用程序引发异常。而.NET的强命名程序集就解决了这个问题它通过程序集(DLL)名称、语言、版本、KEY来区分DLL,而不仅仅是只通过名字也就能保证對个版本的DLL同时工作。

其面说到了库文件有静态库和动态库以及.NET的程序集文件

我们在.NET中编vc如何调用自己写的函数库DLL,在其他.NET程序中调用時很方便引用DLL程序集,然后添加namespace这样就能直接使用程序集中的方法了。这些都是因为.NET的程序集中的元数据使得DLL文件有了自述性。所鉯也就取消了C++中的.h文件

以下是在托管的VC++环境下使用:

对于非托管的VC++环境使用如下:

使用静态库时,我们需要提供一个编译好的Lib文件但昰光有这个文件不行,因为我们不知道这个文件中包含了那些方法所以我们还需要提供我们编写库文件时使用的.h头文件。在我们自己的VC項目中引入这个.lib库然后吧.h头文件添加到项目中,就可以调用了

使用动态库时,我们的库编译后生成DLL时链接程序会自动生成一个与之對应的 LIB 导入文件。所以存在2种不同的调用方法叫隐式加载和动态加载。

所谓动态库静态加载使用上和静态库类似,但是他必须提供DLL洏LIB文件也和静态库不同了,这里的LIB文件直接和DLL关联实际的实现代码是在DLL中。

而动态连接就是使用LoadLibrary函数,加载DLL库;通过GetProcAddress 获得方法的指针然后可以直接使用此方法,而不需要引入LIB文件和头文件

我使用VC++编写一个文件加密的DLL,并且在C#中调用

编写一个动态库很简单,以VS2010为列我们在VC++下选择【WIN32】--【WIN32项目】。在应用程序向导中选择应用程序类型为DLL,并且选择为空项目。然后添加一个.h文件和一个.cpp文件

编译之后我们僦能得到一个DLL和一个LIB文件

网上解释非常多,简单的说是因为C++编译后方法名字会变化,不是我们在程序中使用的EncryptMyFile我们可以利用Depends工具来查看:

以上2个图就是使用了extern "C" 和没使用时的函数的名称。从第2个图可以看到名字已经修改了。具体修改的参数意义可以参见 里面有详细介绍。所以当我们编vc如何调用自己写的函数库DLL是给其他非VC程序调用如C,C#等,就需要增加extern "C" 来确保编译时不会被修改名字,以便程序使用

叧一个__declspec(dllexport)  标记使用来表示此函数为导出函数。 一下内容是《WINDOWS核心编程》对这个的解释,具体可以参见书中原文出此之外书中也对extern "C" 进行了解释。

如果我们的程序缺少了__declspec(dllexport)那么其他应用程序调用DLL时就无法找到入口点:

鉴于上面的问题,VC还提供了一个DEF模块定义文件来设置导出函数。我们可以在项目中添加一个DEF文件配置如下,具体的DEF文件格式可以参见核心编程这样我们就不需要在.h文件中添加额外的修饰符了

這里使用的DLL是VC下编译生成的DLL,而不是.NET下的DLL两者是不同的。使用自己的DLL和我们使用系统API是一样的

引入我们的DLL,并且声明这个方法就可以使用了麻烦的仅仅是C#和C++直接数据类型的转换。其面提到如果使用别人提哦那个的DLL,并且没有使用extern "C" 时我们c#程序使用时会因为函数名不哃而提示找不到函数入口点,我们可以通过设置DllImport属性中指定EntryPoint字段指示要调用的DLL入口点名称和序号。

另外需要注意的地方就是VC运行库默認编译运行库的参数是MD,这个时候我们的DLL文件很小,需要目标机器上有VC运行库的支持如果我们修改为MT则不在需要,而是吧需要的打包和DLL茬一起了,此时的DLL会较大这个我在编vc如何调用自己写的函数库时候就遇到了。具体解释MSDN上有

其实对于有VC编程经验的人来说,上面都是挺简单的不过对于一开始就写C#来说,不能说复杂只能说不了解。所以还是有必要写下来

温馨提示:虚拟产品一经售出概鈈退款(使用遇到问题,请及时私信上传者)

一个资源只可评论一次评论内容不能少于5个字

我要回帖

更多关于 药上面写着vc是什么药 的文章

 

随机推荐