C#调用C和C++函数的一点区别

最近做U800电话的二次开发,需要调用厂商的C函数库来打电话,后来想加入通话录音功能,但发现程序默认生产的WAV文件过大,又找了个WAV转MP3的C++函数库程序,出了点问题。下面是转MP3的程序接口(头文件):

#ifndef _MP3ENC_H_
#define _MP3ENC_H_

int mp3_enc(const char* inWavName,int nRate,const char* outMP3Name);

#endif

按照C#调用非托管程序的约定,声明一个对应的C#函数接口:

 [DllImport("mp3enc.dll", CharSet = CharSet.Ansi)]
 public static extern int mp3_enc(string inWavName, int nRate, string outMP3Name);

然后这样调用改函数:

 mp3_enc(txtWavFile.Text, 32, "222.mp3");

结果出现这样的异常信息:

1 对 PInvoke 函数“U800Test!U800Test.Form1::mp3_enc”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

跟原来调用C函数库的方法仔细对比,发现没有区别,而C函数代码却可以正常使用: 打电话的C函数接口:

USBDLL_API int _stdcall StartDial(int iDevIdx,const char* szDest);    //发送拨号命令

对应的C#函数接口:

  [DllImport("UsbDll.dll", CharSet = CharSet.Ansi)]
  public static extern int StartDial(int iDevIdx,string szDest);

再看看C++的调用函数的错误信息,难道是C++字符串类型不一致?需要C++使用Unicode 字符?于是将C#的函数接口改成:

 [DllImport("mp3enc.dll", CharSet = CharSet.Unicode)]
public static extern int mp3_enc(string inWavName, int nRate, string outMP3Name);

结果C#程序直接崩溃,连Try....Catch.... 都没用。

最后,在网上搜索了半天,发现有这个说法:

DllImport还有一个CallingConvention的属性,默认值是CallingCovention.Stdcall,  此处更改成Cdecl(c/c++默认调用方式)就可以了。VS2010下必须得指定这个属性才能运行, 同样的代码在VS2008下却不存在这样的问题, 奇怪 ...

正确的C++ 函数C#调用接口应该是这样:

[DllImport("mp3enc.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
 public static extern int mp3_enc(string inWavName, int nRate, string outMP3Name);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android相关

Android中的Proguard介绍

ProGuard是一个Java Class文件的Shrinker,optimizer,obfuscator以及Preverifier。

1593
来自专栏散尽浮华

Linux下针对服务器网卡流量和磁盘的监控脚本

2234
来自专栏技术之路

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细...

2988
来自专栏张善友的专栏

IBatisNet基础组件

DomSqlMapBuilder DomSqlMapBuilder,其作用是根据配置文件创建SqlMap实例。可以通过这个组件从Stream, Uri, Fil...

3165
来自专栏一个番茄说

让你在WebView中用JS调Native Object

之所做这个东西,源于之前项目中需要把一些页面用webView来呈现,但是web中需要调用native的方法,比如获取本地存的某些数据、调用摄像头等等,这里也就是...

1103
来自专栏debugeeker的专栏

adobe flash player升级coredump分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

631
来自专栏大内老A

ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator

对于ASP.NET MVC基于标注特性的Model验证,很多人只知道应用在数据类型及其属性上用于定义验证规则和错误消息的ValidationAttribute。...

22910
来自专栏跟着阿笨一起玩NET

对比MS Test与NUnit Test框架

项目中进行Unit Test时,肯定会用到框架,因为这样能够更快捷、方便的进行测试。

872
来自专栏陈仁松博客

UWP基础教程 - XAML开篇

XAML是英文Extensible Application Markup Language的缩写,中文可以称为“可扩展应用程序标记语言”,是基于Extensiv...

4258
来自专栏每日一篇技术文章

Foundation-NSCache

第二步 使用NSCache 把对象缓存起来,evictsObjectsWithDiscardedContent 这个属性必须设置为true

1452

扫码关注云+社区

领取腾讯云代金券