【C#】调用C++编写的dll在IIS中报错,vs里面没有问题

        项目中,用C#开发了一个web服务后台,提供接口以供外部调用。最近功能更新,更改了某个接口的实现,发版并测试之后,发现在vs中调试一切正常,但是发布到IIS中运行,就会出现问题,该接口调用不了。由于是java web调用C#后台,调用后台的代码,是由web服务后台的wsdl文件生成,现在接口调用出错,加上只有此次更改后的接口调用出错,其它接口一切正常,而且在vs编译器下又一切正常。所以,第一直观肯定是这里的java调用出现问题。

第1步,确定是java调用问题。
        尝试重新生成java调用web后台的代码。因为VS中一切正常,IIS中就不行,于是发布到IIS之后,利用运行起来的wsdl文件,生成新的调用代码,试了之后,还是不行。通过解析java war包后的文件夹内容,然后进行比较,发现其实war包的内容是一样的,也就是说生成java调用C# web后台的代码没有变化,问题不在这里。

第2步,确定是IIS配置问题。
        这个解决方式百度上有很多,基本上就是修改IIS配置,同时对调用的dll,通过右键属性->安全,授予IIS用户权限。处理之后,依然没有解决问题。

第3步,确定是tomocat配置问题。
        查看tomocat下的日志,发现有日志记录,意思是调用接口的类中,出现了javax.xml.ws.WebServiceException: java.net.SocketException: Connection reset错误,网上有建议将生成的wsdl文件里面的接口地址处理成要发布的IP地址,没有解决此问题。另外tomocat的配置本来就没有修改,之前就没有问题,所以紧接着确定是代码问题。

第4步,调用的dll,编译生成的代码有问题。
        跟写dll的C++沟通,基本确定没问题,毕竟,如果有问题的话,那么在编译器调试时就会出现问题。

第5步,调用dll的C#代码有问题。
        好不容易来到了第四步,问题真就出在这里!发现的方式是,在调用dll前面和后面直接返回接口调用,实际效果是一个可以一个不可以,由此锁定问题。在进行C#调用C++中,代码如下:

[DllImport("SDK.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern string TEST_SDK_GetVersion();

        上面是一个简单的调用代码,获取版本号,返回的是string类型。但实际在跟C++工程师沟通后,得知该函数在C++中,返回的是string类型的指针。这里涉及到内存管理的问题,因为VS和IIS应用程序池的内存管理方式存在差别,所以导致VS里面运行正常,发步IIS后出现问题。
        修改方式:返回值不用string,采用IntPtr。IntPtr用于表示指针或句柄的平台特定类型,C#中的IntPtr类型称为“平台特定的整数类型”,你也可以理解成变相的指针,这里由于我们需要的还是string类型的值,所以返回值不能直接使用,还需要转换。所以修改该函数返回值类型,并添加一个方法来间接调用:

[DllImport("SDK.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr TEST_SDK_GetVersion();

private string Get_TEST_SDK_GetVersion()
{
    return Marshal.PtrToStringAnsi(TEST_SDK_GetVersion()); //转换为C#托管环境的string
}

        现在,改为调用Get_TEST_SDK_GetVersion方法即可。

总结:查看MSDN文档,Marshal.PtrToStringAnsi(IntPtr)方法为托管字符串的副本从非托管 ANSI 第一个空字符之前的所有字符 String, 并且每个将 ANSI 字符扩展为 Unicode,对于自定义封送处理或混合托管和非托管代码时很有用。通过该方法,将非托管C++的string指针的值,在托管代码C#中获取到。这样,也就理解了为啥在VS中调试或运行一切正常,而发布IIS上就有问题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值