Он смотрит на меня, как будто у вас есть редкий решатель код, написанный на C и пытаются ссылку на вашу программу Delphi. Я думаю, что у вас есть фундаментальная проблема в том, как вы заявили о своем внешнем импорте. Вместо того, чтобы ответить на заданный вами вопрос напрямую, я покажу вам, как я считаю, правильным способом объявить и называть такой внешний импорт.
Первое, что я бы сказал, это то, что большие статические типы массивов, которые вы объявили, не являются тем, что вам нужно здесь. Эти типы массивов иногда могут быть полезны, но только на самом деле, когда вы добавляете другой массив в PADouble = ^ADouble
. В вашей ситуации вам вообще не нужны эти массивы, и я предлагаю удалить их.
я буду считать, что вы вызываете функцию с именем solve
, который принимает n
, nz
, Ap
, Ai
, Ax
и b
в качестве входных параметров и возвращает x
в качестве выходного параметра. Функция возвращает x
такой, что A*x=b
, где A
- размерная квадратная разрешенная матрица n
, указанная Ap
, Ai
и Ax
. Параметр nz
указывает количество ненулевых элементов. Несомненно, фактическая функция будет отличаться в деталях, но концепции будут одинаковыми. Например, обычно вызывается nz
от Ap[n]
, но эти детали вам разрешат.
Я предлагаю вам объявить функцию для получения параметров в качестве указателей на первый элемент. Таким образом, объявления функций выглядят так:
function solve(
n: Integer;
nz: Integer;
Ap: PInteger;
Ai: PInteger;
Ax: PDouble;
b: PDouble;
x: PDouble
): Integer; cdecl; external;
Затем вам нужно заполнить свои разреженные матричные массивы. Объявить их как динамические массивы:
var
Ap: TArray<Integer>;
Ai: TArray<Integer>;
Ax: TArray<Double>;
....
SetLength(Ap, n);
Ap[0] := ...;
....
SetLength(Ai, nz);
Ap[0] := ...;
....
SetLength(Ax, nz);
Ax[0] := ...;
....
Я ожидаю, что вы будете знать только значение n
, nz
и т.д. во время выполнения и что содержание матрицы будет заполнено с помощью петли и так далее. Код в вопросе - это, по-видимому, тестовый код, чтобы попробовать и проверить внешний код. Ответ Арно дает вам здравый совет о том, как заполнить динамический массив.
Вам также необходимо инициализировать b
и x
:
var
b: TArray<Double>;
x: TArray<Double>;
....
SetLength(b, n);
b[0] := ...;
....
SetLength(x, n);
// no need to initialise values of x[i] since it is the output
Теперь вы можете вызвать функцию:
var
retval: Integer;
....
retval := solve(n, nz, PInteger(Ap), PInteger(Ai), PDouble(Ax),
PDouble(b), PDouble(x));
Один конечный пункт, converning использование общих массивов. Поскольку вы используете современный Delphi, я предлагаю использовать общие динамические массивы. Итак, вместо array of ...
вы должны использовать TArray<...>
. Причина этого в том, что общие типы имеют разные правила совместимости типов из динамических массивов старого стиля. В приведенном выше коде, например, b
и x
являются совместимыми с назначением. Но если они были объявлены следующим образом:
var
b: array of Double;
x: array of Double;
тогда они не были бы совместимыми с присвоением. Вы можете обойти эту проблему, объявив тип, TDoubleArray = array of Double
. Однако, если вы используете общий массив, вы можете использовать общие классы контейнеров, такие как TList<T>
, чем возвращаемые значения типа TArray<T>
, которые вы можете легко использовать.
Я знаю, что это не совсем тот вопрос, который вы задали, но у меня такое чувство, что оно может быть полезно для вас.
Это может помочь, если вы точно определите, что вы пытаетесь сделать с помощью своих массивов. Код, который вы написали для инициализации ваших массивов, никогда не работал ни в одной из версий Delphi/Pascal, а страницы Руди не говорят, что они должны быть AFAICT, потому что это недопустимый синтаксис, и Руди знает лучше (если он на самом деле говорит, что, пожалуйста укажите ссылку). Delphi позволяет инициализировать постоянные массивы (не с этим синтаксисом) или динамические массивы с использованием синтаксиса псевдоконструктора. Трудно сказать, как вы должны его изменить, потому что вы не дали понять, что вы пытаетесь сделать. –
Это выглядит как разреженный матричный решатель. Какой из них вы используете из интереса. Мне нравится CSparse Тима Дэвиса, который я завернул, скомпилировав код C в .obj, а затем связав его точно так же, как и вы. –
Кен - извините, ссылка, на которую я имею в виду, включает преобразования C-to-pascal. На странице Руди упоминается это [здесь] (http://rvelthuis.de/articles/articles-convert.html здесь) в разделе «Параметры массива». @David Это точно решатель, с которым я работаю, рад узнать, что путь, который я решил пойти, сделал кто-то еще ха-ха. –