Console.WriteLine("{0:X}", handle.ToInt32());
else
Console.WriteLine("{0:X}", handle.ToInt64());
if (!DeleteObject(handle))
Console.WriteLine("Can't delete the logical font");
}
}
}
Теперь, когда кажется, что все ясно, хочется попытаться вызвать функции, экспортируемые нашей DLL. Выбросьте все лишнее (или сохраните под другим именем) и вновь приведите файл Class1.cs в то состояние, в котором он был две страницы назад. Затем внесите изменения в класс GaussTest так, чтобы он стал.
class GaussTest
{
[DllImport("C:/Debug/MyDLL.dll")]
public unsafe static extern void AllocMatrix (ref double** a, int ny, int nx);
[DllImport("C:/Debug/MyDLL.dll")]
public unsafe static extern void ClearMatrix (ref double** a, int n);
[DllImport("C:/Debug/MyDLL.dll")]
public unsafe static extern bool Gauss (double** a, double[] x, int n);
public unsafe void FillMatrix (double** a, int n) // Генерирование расширенной матрицы
{
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
a[i][j] = Math.Sin((i+j+.2) / 20.0) + Math.Log (i + j + 1.0);
}
for (int i=0; i<n; i++) // Вектор правых частей
{
for (int j=0, a[i][n]=0.0; j<n; j++)
a[i][n] += a[i][j] * (j+1);
}
for (int i=0; i<n; i++) // Вывод плохой матрицы
{
Console.WriteLine ();
for (int j=0; j<n+1; j++)
Console.Write ("{0:F3}, ", a[i][j]);
}
}
[STAThread]
static unsafe void Main()
{
GaussTest test = new GaussTest();
double** a = null;
int n = 1;
//====== Этот цикл позволяет исследовать решение линейных систем с плохо-обусловленной матрицей
while (true)
{
Console.Write ("\n\nEnter matrix dimension: ");
n = int.Parse(Console.ReadLine());
if (n < 2 || 15 < n)
break;
AllocMatrix (ref a, n, n+1);
double[] x = new double[n];
test.FillMatrix (a, n);
Gauss (a, x, n); // Исключение по Гауссу
ClearMatrix (ref a, n);
Console.WriteLine ("\nExported progress: {0}%\n", progress);
Console.WriteLine ("\n\n\tSolution\n\n");
for (int i=0; i<n; i++)
Console.Write ("{0:F2}, ", x[i]);
}
Console.WriteLine ("\n\n");
}
Заметим, что если в классе все методы опасные, то вместо того, чтобы помечать как unsafe каждый метод, можно вставить этот спецификатор в описание класса (в качестве упражнения так и сделайте), например:
public unsafe class GaussTest { . . . }
Далее, обратите внимание на описатель ref. Объясните себе, почему он встречается не везде, где мы работаем с матрицей, а только при вызове двух функций. В общем, за исключением мелких, но важных деталей, код вполне соответствует тому, что был в предыдущем клиентском приложении, написанном на языке С++. Но если вы запустите приложение, вас постигнет разочарование. Система не способна обнаружить ни одной точки входа, то есть глобальной функции, экспортируемой DLL. Этот отказ выглядит так:
Unable to find an entry point named AllocMatrix in DLL C:/Debug/MyDLL.dll.
В чем же дело? На этот вопрос поможет ответить утилита по имени dumpbin, которая имеется в операционной системе. Она позволяет выудить из DLL информацию обо всех экспортируемых ею сущностях. Для ее запуска необходимо воспользоваться командной строкой. Нажмите комбинацию клавиш LWin+R. Я вас поймал? Да нет же. Конечно, все знают клавишу LWin — "Левая Windows". Ищите ее слева, она похожа на Windows. Далее, в окне диалога Run наберите Cmd и нажмите Enter. Вы попали в царство, похожее на DOS. В командной строке наберите команду, которая допросит нашу DLL.
dumpbin -exports C:/Debug/MyDLL.dll
В ответ утилита dumpbin выведет достаточно много строк и вы увидите причину отказа.
Время бежит неумолимо, довольно быстро изменяются версии Windows и весьма вероятно, что вы не найдете утилиту dumpbin.exe, которая ранее была в папке C:\Program Files\Microsoft Visual StudioXXX\VC\bin. Если вы не обнаружили утилиту, то либо поверьте тому, что написано далее, либо установите утилиту, но будьте осторожны, так как хакеры часто ловят нас на попытке установить полезный софт. Лучшим решением может быть чтение статьи (и использование ее кода) по ссылке: http://www.codeproject.com/KB/cs/VisualDumpbin.aspx.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.