当前位置: 代码迷 >> C# >> C#调用C++dll出错ACCESS VIOLATION
  详细解决方案

C#调用C++dll出错ACCESS VIOLATION

热度:113   发布时间:2016-05-05 04:12:06.0
C#调用C++dll报错ACCESS VIOLATION
原帖地址:http://bbs.csdn.net/topics/391012458
代码改了一下,问题还没有解决。于是重开一个贴

-----------------------------------------------------C#代码

namespace WpfApplication2
{
    class MyClass1 : INotifyPropertyChanged  
    {     
    public MyClass1()
    {
        result="null";
    }
    private string result;

    public string Result
    {
        get { return result; }
        set { result = value;
            if (PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Result"));
            }
        }
        
    }
    public event PropertyChangedEventHandler PropertyChanged;
    }
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
  
    public class mytransdll 
    {
        [DllImport("mytransdll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public static extern int mytransfunc(StringBuilder exportpath, StringBuilder importpath);
    }
    public partial class Main : Window
    {

        MyClass1 myout=new MyClass1 ();       
        private StringBuilder exportpath;        
        private StringBuilder importpath;      
        public Main()
        {
            InitializeComponent();
            myout.Result = "there will show ,if transform is ok ";// Result 赋值应该放到Main的构造函数或者窗口的Loaded事件中赋值的。
           //把结果binding上去。。。请注意,XAML里的binding并不能访问C#里的变量,而C#里的变量却可以访问XAML
            Binding bind1 = new Binding();
            bind1.Source = myout;                    
            bind1.Path = new PropertyPath("Result");
            this.MyLabel.SetBinding(Label.ContentProperty, bind1);  

        
        }
       private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            //int isornotsuccess = 1;
           
            int isornotsuccess = mytransdll.mytransfunc(exportpath, importpath);
             myout.Result = " Transforming,please wait....";
            Binding bind3 = new Binding();
            bind3.Source = myout;
            bind3.Path = new PropertyPath("Result");
            this.MyLabel.SetBinding(Label.ContentProperty, bind3);    //按下按钮之后马上显示正在传输
             if (isornotsuccess == 1)
            {
                myout.Result = exportpath.ToString() ;
                Binding bind2 = new Binding();                   
                bind2.Source = myout;
                bind2.Path = new PropertyPath("Result");
                this.MyLabel.SetBinding(Label.ContentProperty, bind2);                //这里写成功后的反应
            }
        }

        private void textBox1_KeyDown_1(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter) //key是一个类,这是一个类的判断
            {
                StringBuilder exportpath=new StringBuilder(this.textBox1.Text,200);
                 
                
            }
        }



---------------------------------------------------C++编写的DLL

//

#include "stdafx.h"
#include "stdio.h"
#include"pcap.h"
#include<WinSock.h>
#include"packet32.h"
#include<Win32-Extensions.h>
#include "stdlib.h"



extern "C" _declspec(dllimport) int mytransfunc(char* exportpath,char* importpath);
int mytransfunc(char* exportpath,char* importpath)
{
//和EXPORTPATH无关的代码
char A[]="regenerate_original_picture.txt";
char PA[1024];
char exportpathvalue=*exportpath;
//!!!!高能,就是这句出问题。不管是用这种方法中转还是直接调用*exportpath都出现报错
sprintf(PA,"%s\\%s",exportpathvalue,A);//连接字符串
FILE *fpopen = fopen(PA, "rb");
//和EXPORTPATH无关的代码
}


-----------------------------------------问题
C#编写了一个UI界面,调用DLL的时候传入文件所在地址,然后由DLL对其操作
测试过DLL程序的正确性。

之前大神们说的,如使用stringbuilder,DllImport函数的参数的设定都不管用。有网友说是关于托管代码和非托管代码内存管理的问题。。。楼主是新手,不太明白,还请指教。
------解决思路----------------------

还没搞定?
------解决思路----------------------
[DllImport("mytransdll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public static extern int mytransfunc([MarshalAs(UnmanagedType.LPStr)]string exportpath, [MarshalAs(UnmanagedType.LPStr)]string importpath);
------解决思路----------------------
因为你的exportpath没有初始化,传了null到C++,引发Access Violation异常。

解决方法:
1、去掉75行StringBuilder本地声明:
   [删]StringBuilder[/删] exportpath=new StringBuilder(this.textBox1.Text,200);
2、或者,更好的是,exportpath即用即拿(不用声明为类成员,也不需要textBox1_KeyDown_1事件):
       private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            StringBuilder exportpath=new StringBuilder(this.textBox1.Text,200);
            int isornotsuccess = mytransdll.mytransfunc(exportpath, importpath);


------解决思路----------------------
char exportpathvalue=*exportpath;
sprintf(PA,"%s\\%s",exportpathvalue,A);//连接字符串

这是另外的一个错误。
%s将期待一个字符串指针,但你传入了一个char(char的取值范围是0~255),小数值指针将导致’违规访问‘。
  相关解决方案