C # ShowDialog () выдает ошибку из-за импорта C ++ DLL - PullRequest
0 голосов
/ 22 сентября 2011

Эта программа на C # работает без использования showdialog (), но создает исключение "нарушение доступа к системе", когда я пытаюсь использовать showdialog ().Странно !!

Код C #

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace w_CSharp_GUI_1
{
    public partial class Form1 : Form
    {
        private String W_Addr,C_Addr,Pic_Addr="lol";

        [DllImport("face_proj_trial_dll.dll")]
        public static extern string f_detect(string path);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
        OpenFileDialog openFileDialog2 = new OpenFileDialog();

        openFileDialog2.ShowDialog(this);

            Pic_Addr = (f_detect("C:\\pic.jpg"));

            textBox1.Text = Convert.ToString(Pic_Addr);
        }

    }
}

Код C ++:

#include "face_detect_DLL.h"

extern "C" __declspec(dllexport) char* _stdcall f_detect(char* path)
{
    return path;
}

Ответы [ 2 ]

1 голос
/ 22 сентября 2011

Функции, которые возвращают строку, являются проблемой управления памятью. Память для строки должна быть освобождена. Маршаллер pinvoke собирается вызвать CoTaskMemFree () для возвращаемой строки. Это может привести к сбою в Vista и выше, тихой утечке памяти в XP, поскольку строка не была выделена CoTaskMemAlloc.

Вам нужно будет объявить тип возвращаемого значения как IntPtr, чтобы маршаллер не смог это сделать. И соберите его сами с помощью Marshal.PtrToStringAnsi (). Это решает сбой, но не утечку памяти. Вам нужно объявить функцию как void f_detect (const char * path, char * somevalue, size_t somevaluebuffersize), чтобы вызывающая сторона могла передавать свой собственный буфер. StringBuilder на управляемой стороне.

1 голос
/ 22 сентября 2011

Это совсем не удивительно.Вы возвращаете строку C, которая была фактически создана маршаллером C #.Затем маршаллер дважды пытается освободить эту память.Один раз в качестве возвращаемого значения и один раз для параметра, переданного в DLL.Первое освобождение завершится ошибкой, потому что память не была выделена распределителем, который предполагает маршаллер C #.

В любом случае, вы просто не хотите возвращать char* из вашей DLL.Я не уверен, что вы действительно хотите сделать, но нормальные шаблоны со строковыми вызовами P /:

  1. Для сортировки строк из C # в C ++ объявите их как string в вашем C # и char* в C ++.
  2. При переходе в другую сторону используйте StringBuilder.Выделите буфер перед вызовом и используйте MarshalAs.В сети есть множество примеров этого шаблона.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...