Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: проблема использования C++ ATL DLL в C#, иногда при вызове DLL из C# server error  (Прочитано 22066 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
bublik478
Гость
« : 22-02-2008 00:16 » 


проблема в следующем:

на С++ создана (ATL) DLL для использование в C# проекте.

в DLL пока тока одна функция, передаётся указатель на массив чисел INT (координаты X и Y, это полигон) и точка с координатами X,Y. Функция определят лежит ли точка внутри полигона или снаружи.

тест работает нормально, но в многократном вызове этой функции из C#  (раз 50-150 подряд) иногда выскакивает следующая ошибка:

"The server threw an exception."   

если у кого есть опыт посдкажите пожалуйста хотябы где начать рыть. С++ тока начал изучать и не хочу отказываться, работает быстрее, темболее есть возможность компилировать в Native code.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 22-02-2008 04:11 » 

1) а покажи пример массива, как ты его заполняешь и передаёшь
2) может написать свою функцию ?
Записан

bublik478
Гость
« Ответ #2 : 22-02-2008 13:38 » 

с удовольствием!
вот сама функция в Polygone классе
Код:
	static int __fastcall PointInPoly(LONG Px, LONG Py, LONG* Vx, LONG* Vy, LONG n)
{
LONG  cn = 0;    // the crossing number counter
int i = 0;
// loop through all edges of the polygon
while(n) {// edge from V[i] to V[i+1]
if (((Vy[i] <= Py) && (Vy[i+1] > Py))    // an upward crossing
|| ((Vy[i] > Py) && (Vy[i+1] <= Py))) { // a downward crossing
// compute the actual edge-ray intersect x-coordinate
float vt = (float)(Py - Vy[i]) / (Vy[i+1] - Vy[i]);
if (Px < Vx[i] + vt * (Vx[i+1] - Vx[i])) // P.x < intersect
++cn;   // a valid crossing of y=P.y right of P.x
}
i++;
n--;
}
return (cn&1);    // 0 if even (out), and 1 if odd (in)
}
« Последнее редактирование: 22-02-2008 15:21 от Алексей1153++ » Записан
bublik478
Гость
« Ответ #3 : 22-02-2008 13:42 » 

а это находится в simple ATL объекте math. у которого есть интерфейс


STDMETHODIMP Cmath::PointInPolygon(LONG px, LONG py, LONG* xx, LONG* yy, LONG n, LONG* plResult)
{
//      __try
//    {
   
              *plResult = Polygone::PointInPoly(px, py, xx, yy, n);
   
//     }
 //       __except (EXCEPTION_EXECUTE_HANDLER)
 //   {
   //   //printf("Exception handler %lX\n", _exception_code());
 //       Sleep(10);
   //   *plResult = -10;
   //}

   return S_OK;
}
« Последнее редактирование: 22-02-2008 13:53 от bublik478 » Записан
bublik478
Гость
« Ответ #4 : 22-02-2008 13:43 » 

сам интерфейс который находится в DLL.idl файле:

interface Imath : IUnknown{
   [helpstring("method plg_pin")] HRESULT plg_pin([in] LONG px, [in] LONG py, [in] LONG* xx, [in] LONG* yy, [in] LONG n, [out,retval] LONG* plResult);
};
Записан
bublik478
Гость
« Ответ #5 : 22-02-2008 13:52 » 

массив создаётся в С#  а в с++ я передаю указатель на первый член этого массива, тип данных массива и размер массива.
 из c# вызываю так:

int[] xs = new int[100];
int[] ys = new int[100];

далее заполняю xs и ys.
и теперь вызов с++

myDLL.math m = new myDLL.math()
if(m.PointInPolygon(Px,Py, ref xs[0], ref  ys[0], ys.length))
{
     // наша точка Px, Py лежит внутри многоугольника!
}

у многоугольника первая точка и последняя одинаковы! он замкнутый!
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 22-02-2008 15:27 » 

а массив каждый раз содержит разные данные или одни и теже ?

если разные - при каком содержимом массива происходит вылет  и происходит ли это регклярно ?

(проверить ничего не могу за неимением шарпа )
Записан

bublik478
Гость
« Ответ #7 : 22-02-2008 20:07 » 

скажем так размерность массива разная бывает, а тим данных один и тотже.

создаётся первый массив (точки многоугольника) и проверятся около 30-40 точек внутри полигона они или нет, потом следующая серия точек проверяется для следующего полигона и т.д.

и вылетает где самые большие полигоны (массивы) и где чаще всего используется эта функция, но не всегда на одном и томже месте!
Записан
bublik478
Гость
« Ответ #8 : 22-02-2008 20:08 » 



кстати а как лучше передавать данные в С++???
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 22-02-2008 20:11 » 

а что означает - передавать данные в c++ ?
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 22-02-2008 20:12 » 

а запусти в дебаге то - где именно вылетает ? Или в шарпе низя так ?
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 22-02-2008 20:23 » new

Я бы для отладки добавил бы проверку ассертами Vx и Vy на неравенство NULL до цикла и писал бы в лог значения Vx[ i ], Vy[ i ], Vx[i+1], Vy[i+1]. Хоть видно будет, что в массиве хранится именно то, что нужно.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
bublik478
Гость
« Ответ #12 : 22-02-2008 21:00 » 

debug сишарпа показывает что при очередном вызове с++ вункции генерируется ошиба как написано в первом сообщении.

все числа перед передачей в с++ проверяются, они не равны NULL и данные корректны
« Последнее редактирование: 22-02-2008 21:03 от bublik478 » Записан
bublik478
Гость
« Ответ #13 : 22-02-2008 21:02 » 

а что означает - передавать данные в c++ ?

я имелл виду например как лучше было бы передать массив из c# в с++ и что лучше передавать массив стандартного типа  или например создать структуру в с++ а заполнять её в c# и передавать обратно в с++

Не понял
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 22-02-2008 21:20 » 

bublik478, про дебаг... Просто раз уж ты показал исходный код (коли среда тебе это позволяет), то может работает следующее: например ищу я глюк, который известно, когда возникает. В VC6 я могу без точек останова запустить свою программу в дебаге, а когда она отвалится , появляется окно с кнопками - прервать, повторить и ещё чивота там. Жму повторить - оказываюсь на строке ассемблерного кода, где произошла некорректное действие (если повезёт - то и в строке исходника). Открываю стек вызовов , смотрю, откуда перешли сюда, какие там значения переменных были и т.д. Я про это.

Цитата
я имелл виду например как лучше было бы передать массив из c# в с++ и что лучше передавать массив стандартного типа  или например создать структуру в с++ а заполнять её в c# и передавать обратно в с++
понятия не имею ) Наверное , лучше массив стандартного типа
Записан

bublik478
Гость
« Ответ #15 : 22-02-2008 22:19 » 

ok, спасибо за совет, попробуем дебагить с++.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 22-02-2008 22:24 » 

да это не совет, а предположение )
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 23-02-2008 07:28 » 

Цитата: bublik478
myDLL.math m = new myDLL.math()
Это создание COM-объекта, как я понимаю? Если мне память не изменяет, COM-объекты имеют интерфейс IDisposable. Сборщик мусора, конечно, всё подберёт, но авось поможет явный вызов удаления COM-объекта. Тогда надо писать:
Код: (Text)
myDLL.math m = new myDLL.math();
...
m.Dispose();
или, используя синтаксическую конструкцию:
Код: (Text)
using(myDLL.math m = new myDLL.math())
{
...
}
Что одно и то же.

Впрочем, это всё гадание на кофейной гуще и метод тыка.
« Последнее редактирование: 23-02-2008 07:30 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
bublik478
Гость
« Ответ #18 : 23-02-2008 22:20 » 

dimka,

чтоб использовать метод Dispose
или запись в виде
using()
{

}

где сразу после выхода за фигурные скобки вызывается Dispose.  то надо чтоб объект поддерживал интерфейс IDisposable!

но моя dll этого не поддерживатеб и это я нигде не прописывал!

а вот чтоб мгновенно освободить занимаемую com объектом память, можно пользоваться следующим:

System.Runtime.InteropServices.Marshal.ReleaseComObject(наш сом объект);
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines