Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Вызов функций из dll для изменения компонентов


Автор: kiler4747 1.6.2011, 22:06
Написал программу для копирования папки на C#, а сейчас решил написать сами функции на C++(dll) и сделать многопоточной, но возникает ошибка входе в функцию из dll, проверял вызов функции в С++ - все нормально. Хочу запустить сначала фоновый поток для поиска количества файлов и увеличивать каждый раз maximum в progressBar(bar) и сразу запустить поток для копирования.

Код

...
class MyClass
{
    ProgressBar bar;
    string folderout{get; set;}
    string folderin{get; set; }

    MyClass(ProgressBar bar1)
    {
        bar = bar1;
    }
    ...
    public void runcopy(string outl, string inl)
            {
                folderout = outl;
                folderin = inl;
                Thread thr = new Thread(UpdateProgressMax);
                thr.IsBackground = true;
                thr.Start();
                CopyFolder(outl + "\\", inl + "\\");
            }

    [DllImport("Exploer_03(dll).dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
            extern static void MaxValueWchar(string outl,ref long maxbar);

            void UpdateProgressMax()
            {
                long barr = bar.Maximum;
                bar.Invoke(new MethodInvoker(delegate { MaxValueWchar(folderout, out barr); }));
            }
    ...
}


dll(C++)
Код

extern "C" _declspec(dllexport) void MaxValue(CString Path, long *maximum)
{
    if (Path[Path.GetLength()] != L'\\')
        Path += L'\\';
    HANDLE handle;
    WIN32_FIND_DATA data;
    handle = FindFirstFile(Path + L"*.*",&data);
    do 
    {
        if (handle == INVALID_HANDLE_VALUE)
            break;
        if (data.cFileName[0] == L'.')
            continue;
        if ( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
        {
            MaxValue(Path + data.cFileName, maximum);
        }
        else
            (*maximum)++;
    } while (FindNextFile(handle,&data) != 0);
}

void MaxValueWchar(wchar_t * path, long * lg)
{
    CString Path = path;
    MaxValue(Path, lg);
}


Добавлено через 54 секунды
Что неправильно?

Автор: jonie 1.6.2011, 22:26
давно ли CString стал мапиться на string из C# ? 
мапиться могут только относительно несложный типы, например const TCHAR*, CString тут не прокатит
Цитата

Код

extern "C" _declspec(dllexport) void MaxValue(CString Path, long *maximum)



а, если речь про MaxValueWchar - тогда она вообще из DLL нигде  (по этому коду) не экспортируется.. да и называться она, скорее всего, будет _MaxValueWchar ..

Автор: kiler4747 1.6.2011, 23:15
Согласен что CString несовместим с string(C#), поэтому и писал вторую функцию с wchar_t(C++ знаю не очень).
MaxValueWchar, у меня в программе правильно написано, сюда не все скопировал. Когда и почему функции из dll надо вызывать с добавлением _ , раньше писал без _ и все работало, хотя когда спрашивал насчет вызова функций писали что скорее всего функция должна начинаться с _.
Код

extern "C" _declspec(dllexport) void MaxValueWchar(wchar_t * path, long * lg)
{
    CString Path = path;
    MaxValue(Path, lg);
}


Ошибка возникает при входе в функцию из dll:
File: f:\dd\vctools\vc7libs\ship\atlmfc\include\atlsimpstr.h
Line: 393
Expression: (iChar >= 0) && (iChar <= GetLength())


Автор: kiler4747 3.6.2011, 17:01
Разобрался почему не работали функции - не ту функцию вызывал. Но основная проблема осталась: Как из dll(C++) изменить в ProgressBar свойства Value и Maximum?

Код

...
string folderout{get; set;}
string folderin{get; set; }
...
//функция для подсчета файлов

extern static void MaxValue(string outl,ref long maxbar);
            [DllImport("Exploer_03(dll).dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
            extern static void MaxValueWchar(string outl,ref int maxbar);

            void UpdateProgressMax()
            {
                int barr = bar.Maximum;
                MaxValueWchar(folderout, ref barr);
                bar.Invoke(new MethodInvoker(delegate { bar.Maximum = barr; }));
            }

//функция для копирования папки

[DllImport("Exploer_03(dll).dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
            extern static void copyd(string outl, string inl, ref int lg);
void copyfromdll()
            {
                int lg = 0;
                bar.Invoke(new MethodInvoker(delegate { bar.Value = lg; }));
                copyd(folderout, folderin, ref lg);
                MessageBox.Show("End");
            }

//создание потоков для копирования

public void runcopy(string outl, string inl)
            {
                folderout = outl + "\\";
                folderin = inl + "\\";
                Thread thr = new Thread(UpdateProgressMax);
                thr.IsBackground = true;
                thr.Start();
                bar.Invalidate();
                Thread thr1 = new Thread(copyfromdll);
                thr1.Start();
            }


функции из dll(C++)
Код

extern "C" _declspec(dllexport) void CopyFolder( CString sours,  CString dest, long * num)
{
    HANDLE result;
    WIN32_FIND_DATA data;
    if (sours[sours.GetLength() - 1] != L'\\')
        sours += L'\\';
    if (dest[dest.GetLength() - 1] != L'\\')
        dest += L'\\';
    result = FindFirstFileEx(sours + L"*.*",FindExInfoBasic, &data,FindExSearchNameMatch,NULL,0);
    do 
    {
        if (result == INVALID_HANDLE_VALUE)
            break;
        if (data.cFileName[0] == L'.')
            continue;
        if ( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
        {
            HANDLE handle;
            handle = FindFirstFileW(dest + data.cFileName, new WIN32_FIND_DATA() );
            if (handle == INVALID_HANDLE_VALUE)
                CreateDirectory(dest + data.cFileName,NULL);
            CopyFolder(sours + data.cFileName, dest + data.cFileName, num);
        }
        else
        {
            HANDLE handle;
            WIN32_FIND_DATA date;
            handle = FindFirstFileW(dest + data.cFileName, &date);
            if (handle == INVALID_HANDLE_VALUE)
                CopyFileW(sours + data.cFileName,dest + data.cFileName,false);
            else
                if (date.ftLastWriteTime.dwHighDateTime > 
                    data.ftLastWriteTime.dwHighDateTime)
                    CopyFileW(sours + data.cFileName,dest + data.cFileName,true);
            wchar_t *ti = data.cFileName;
            (*num)++;
        }
    } while (FindNextFileW(result,&data) != 0);
    FindClose(result);
}

extern "C" _declspec(dllexport) void MaxValue(CString Path, long *maximum)
{
    if (Path[Path.GetLength()] != L'\\')
        Path += L'\\';
    HANDLE handle;
    WIN32_FIND_DATA data;
    handle = FindFirstFile(Path + L"*.*",&data);
    do 
    {
        if (handle == INVALID_HANDLE_VALUE)
            break;
        if (data.cFileName[0] == L'.')
            continue;
        if ( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
        {
            MaxValue(Path + data.cFileName, maximum);
        }
        else
            (*maximum)++;
    } while (FindNextFile(handle,&data) != 0);
}

extern "C" _declspec(dllexport) void MaxValueWchar(wchar_t * path, long * lg)
{
    CString Path = path;
    MaxValue(Path, lg);
}

extern "C" _declspec(dllexport) void copyd(const wchar_t *str1,const wchar_t *str2, long * num)
{
    CString st1 = str1;
    CString st2 = str2;
    CopyFolder(st1,st2, num);
}


Автор: jonie 3.6.2011, 23:24
вам надо каллбэк. Я накатал пример (в аттаче) с вызовом калбэка. но использовать его надо крайне осторожно: я не весьма уверен что сам создаваемый делегат не надо сохранять в GC (есть такой метод GCHandle.Alloc - это надо изучать).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)