Otóż problem ma się następująco - mam pewien program w Delphi korzystający z gotowego algorytmu który znajduje się w jednym z modułów. Algorytm ten muszę wykorzystać w aplikacji C#, stąd też pomysł żeby sam moduł odpowiednio przerobić i skompilować jako dll. Tak też zrobiłem, biblioteka zaimportowana w projekcie z następującymi opcjami:
Build action = None
Copy to Output Directory = Copy always
Sprawdziłem czy jestem w stanie wywołać jakąś podstawową funkcję:
[DllImport("ualglin.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void InvMatK(float[,] a, byte n, float eps);
Zwraca poprawny wynik. Szczęście trwało do momentu napotkania poniższej deklaracji w bibliotece:
procedure matrix(var prog:byte;var h2:integer; m,n,s1,s2,s4,s5:byte;d,w:strahl2;axy:daten;eps:dielektr;var c:macd); stdcall;
Gdzie:
const matrixmax = 820;
leitermax = 10;
type vector = array [0..matrixmax] of real;
macd = array [1..matrixmax] of ^vector;
strahl2 = array [0..2*leitermax, 0..2*leitermax] of real;
dielektr = array [0..leitermax] of real;
daten = array [0..leitermax, 0..1] of real;
Tak więc na moje funkcja przyjmuje jako zwracany parametr tablicę wskaźników na tablice liczb zmiennoprzecinkowych(?).
Spróbowałem funkcję zadeklarować następująco:
[DllImport("ualglin.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static unsafe extern void matrix(byte prog, int h2, byte m, byte n, byte s1, byte s2, byte s4, byte s5, float[,] d, float[,] w, float[,] axy, float[] eps, float*[] c);
Raczej nie wierząc w powodzenie tej operacji. Wynikiem tego jest błąd:
System.AccessViolationException was unhandled
HResult=-2147467261
Message=Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona.
Source=Przewody
StackTrace:
w Przewody.CCalc.matrix(Byte prog, Int32 h2, Byte m, Byte n, Byte s1, Byte s2, Byte s4, Byte s5, Single[,] d, Single[,] w, Single[,] axy, Single[] eps, Single*[] c)
w Przewody.CCalc.Calculate(List`1 wires) w c:\Users\Mateusz\Documents\Visual Studio 2012\Projects\Przewody\Przewody\CCalc.cs:wiersz 72
w Przewody.Form1.calcButton_Click(Object sender, EventArgs e) w c:\Users\Mateusz\Documents\Visual Studio 2012\Projects\Przewody\Przewody\Form1.cs:wiersz 571
w System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
w System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
w System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
w System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
w System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
w System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
w System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
w System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
w System.Windows.Forms.Control.WndProc(Message& m)
w System.Windows.Forms.ScrollableControl.WndProc(Message& m)
w System.Windows.Forms.ToolStrip.WndProc(Message& m)
w System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
w System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
w System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
w System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
w System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
w System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
w System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
w System.Windows.Forms.Application.Run(Form mainForm)
w Przewody.Program.Main() w c:\Users\Mateusz\Documents\Visual Studio 2012\Projects\Przewody\Przewody\Program.cs:wiersz 19
w System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
w System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
w Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
w System.Threading.ThreadHelper.ThreadStart_Context(Object state)
w System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
w System.Threading.ThreadHelper.ThreadStart()
InnerException:
Na początku otrzymywałem taki błąd przy próbie skorzystania z jakiejkolwiek funkcji z biblioteki, ale pomogło dodanie do jej głownej funkcji:
begin
IsMultiThread := True;
end.
Próbowałem dodania
uses ShareMem
Jako pierwsze na liście ale bez efektu.
Czy ktoś ma jakiś pomysł jak ten problem rozwiązać, co podać jako parametr po stronie wywołania w C#?
Wiem, że najlepszą opcją byłoby przepisanie całego algorytmu, ale czas mocno nagli, a i sam algorytm to mnóstwo operacji na macierzach których nie rozumiem i szczerze mówiąc nie chciałbym się w nie zbyt zagłębiać.