.net-C#调用c++的dll执行带字符串参数的函数时遇到的问题

问题描述

C#调用c++的dll执行带字符串参数的函数时遇到的问题

我在c++项目中实现函数:
extern "C" __declspec(dllexport) int FUNC1(const char* xmlSta, char* fileOut)
{
return 0;
}
然后编译成动态库a.dll,并在C#项目中引用,
用静态加载的方式,是可以运行的,代码如下(只写调用的部分):
[DllImport("a.dll", EntryPoint = "FUNC1", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int FUNC1(string xmlSta, StringBuilder fileOut);

        StringBuilder sbr = new StringBuilder(10);
        int r1 = FUNC1("abc ", sbr);        //可以运行!

但是用动态加载的方式,却报错,代码如下:

public static class NativeMethod
{
    [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
    public static extern int LoadLibrary(
        [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

    [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
    public static extern IntPtr GetProcAddress(int hModule,
        [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

    [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
    public static extern bool FreeLibrary(int hModule);
}

/// <summary>
/// 函数指针
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
delegate int FUNC1(string xmlSta, StringBuilder fileOut);   

class Program
{
    static void Main(string[] args)
    {
        StringBuilder sbr = new StringBuilder(10);
        //1. 动态加载C++ Dll
        int hModule = NativeMethod.LoadLibrary(@"a.dll");
        if (hModule == 0) return;
        //2. 读取函数指针
        IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "FUNC1");
        //3. 将函数指针封装成委托
        FUNC1 cFUNC1 = (FUNC1)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(FUNC1));
        //4. 测试
        Console.WriteLine(cFUNC1("abc ", sbr));

        Console.Read();
    }
}

报错信息是:托管调试助手“PInvokeStackImbalance”在“E:WCFCPPbintest.vshost.exe”中检测到问题。

其他信息: 对 PInvoke 函数“test!test.FUNC1::Invoke”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

两种方式不都一样吗?为什么第二种方式会报错?因为第一种方式有时运行很慢,要等很久,所以我想用第二种方式在程序启动时先LoadLibrary,之后就不会出现很慢的情况,但是第二种方式总是出错,只有在参数没有字符串类型的情况下才能运行,但是确实需要传字符串参数,哪位高手能够给个指点,代码该如何修改呢?

解决方案

C#默认是stdcall调用约定,你可以把委托改成下面写法
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int FUNC1(string xmlSta, StringBuilder fileOut);

解决方案二:

LoadLibrary以stdcall方式调用,而你的函数是cdecl的约定,所以堆栈不对称。

时间: 2024-10-31 16:16:18

.net-C#调用c++的dll执行带字符串参数的函数时遇到的问题的相关文章

SqlDataReader执行带输出参数存储过程的错误分析

在上一篇随笔:SqlDataReader读取分页数据,pageCount你是肿么了? 遇到了很让人头疼的问题:SqlDataReader执行带输出参数的存储过程总是获取不到输出参数的正确值.这里将解决办法及分析过程列出,为遇到相同问题的小伙伴提供一种解决方案. 在SqlDataReader读取分页数据,pageCount你是肿么了?的评论中有博友提出将 param[2].Direction = ParameterDirection.Output; 该句代码放在执行查询前,确实有这一部分原因.按照

JAVA中对存储过程的调用方法(二) 带输出参数的

二.带输出参数的 1:返回int -------------------------带输出参数的---------------- alter procedure getsum @n int =0, @result int output as declare @sum int declare @i int set @sum=0 set @i=0 while @i<=@n begin set @sum=@sum+@i set @i=@i+1 end set @result=@sum --------

关于c#调用c++ 带指针参数回调函数的问题,求大神帮忙

问题描述 C++函数原型:longSTDCALLIPCNET_StartRealData(longlLoginID,S_REALDATA_INFO*pRealDataInfo,CBRealDatafRealData,Void*pUserData=NULL)参数说明:lLoginIDlong登陆的ID,IPCNET_Login的返回值sRealDataInfoS_REALDATA_INFO*实时数据流的参数结构体fRealDataCBRealData码流数据回调函数,参见CBRealData回调函

ExecuteReader在执行有输出参数的存储过程时拿不到输出参数

异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 后期会在博客首发更新:http://dnt.dkill.net/Article/Detail/312 今天一同志问我这个问题,这个是过程还原: 调用SQLHelper的时候发现输出参数没值了??? 不用sqlhelper也是没有?神马情况? 用sqldataadapter却可以? 吓死宝宝了,赶紧看看啥情况.先换种方法看看 ,,,我去,可以哇!那么是不是ExecuteReader

JAVA中对存储过程的调用方法(一) 不带输出参数的

一.不带输出参数的 ---------------不带输出参数的---------------------------------- create procedure getsum @n int =0<--此处为参数--> as declare @sum int<--定义变量--> declare @i int set @sum=0 set @i=0 while @i<=@n begin set @sum=@sum+@i set @i=@i+1 end print 'the

asp.net webservice调用Delphi的dll

问题描述 asp.net webservice调用Delphi的dll asp.net webservice调用Delphi的dll,执行方法Init(连接Oracle数据库),报错连接超时. 建立个winform程序,调用Init函数可通过,但webservice就是不行. 我是发布在服务器server 2003 32位, IIS发布,发程序发布的文件扔到IIS根目录,dll文件在bin目录下. 调用的这个dll文件又调用了另一个dll,2个dll文件都扔到bin目录下了.不知道是什么原因,w

struts2 0+dll-java web项目调用 vc++的dll文件

问题描述 java web项目调用 vc++的dll文件 我用java 的jni调用vc++写好的dll动态链接库,使用main方法测试没有问题,但是放在web项目的Action中调用就不执行,在static{ System.put.println("load dll..."); System.loadlobrary("ukeyjni"); system.out.println("end load..."); } 上面的调用前后都能打印,在调用的

基于命令行执行带参数的php脚本并取得参数的方法_php技巧

本文分析了基于命令行执行带参数的php脚本并取得参数的方法.分享给大家供大家参考,具体如下: 一.为什么我们要在命令行下运行php脚本呢? 个人理解,主要有二个原因: 1. 利用crontab去跑php,可以给服务器减压,当然在这里有一个条件,就是实时性要求不高.比如:sns中的好友动态,这个实时要求不高,但是数据量比较大,这个时候定时跑的话,会给web服务器,数据库服务器分担不小的压力. 2. 就是我们要定时去完成某一事情,比如:我要删除一个月前,用户留言,这个时候,写的php脚本在cront

javaweb-java视频监控,java怎么操控摄像头,怎么调用厂家的dll

问题描述 java视频监控,java怎么操控摄像头,怎么调用厂家的dll 最近遇到一个项目,有视频监控部分,以前没有接触过摄像头,请问java该如何控制摄像头的行为呢,还有上传和下载摄像头的视频信息到页面上,请大神前辈们指教 解决方案 想问下各位 怎么编写android手机上的应用去取得网络摄像头的资源来呢?我现在遇到的问题就是自己写了一个应用 但是不能够获得网络摄像机的数据 用他自己带的软件是可以的 它是通过登陆摄像头ID然后就可以了,我的为什么不行呢,是不是需要验证呢(用浏览器ip方式登陆摄