#c #vb.net #dll #access-violation
#c #vb.net #dll #нарушение доступа
Вопрос:
Я пытаюсь вызвать C -скомпилированную DLL из VB.net и я столкнулся с некоторыми проблемами. Похоже, есть очевидное решение, но я не могу его понять.
Вот объявление функции в C :
MyFunction(int trailingaveragesize, double sigmasize, int myflag, int sizeSeries, double *Xdata, double *Ydata, int sizeinputparameter, int *averagePairs, double *PositionsSize, double *PnLSize)
Вот как я это вызываю VB.Net:
Call MyFunction(200, 1, 1, 230, a_PriceSeries(0), a_PriceSeries(0), 1, a_Averages(0), a_PositionSeries(0), a_PnLs(0))
Максимальный размер входных матриц определяется sizeSeries (230), а размер всех моих входных матриц равен 10000 (просто чтобы я случайно не переполнялся), но все же я получаю необработанную ошибку AccessViolationException
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Мой вопрос — если я не превышаю границы своих матриц, какие другие причины могут вызвать эту ошибку? Это потому, что я передаю только первую запись в своих матрицах по ссылке, затем она пытается получить доступ к другим элементам этой матрицы? Если да, то как мне это исправить?
Редактировать:
Вот как я объявляю это в VB
Declare Function MyFunction Lib "C:Devasdf.dll" (ByVal trailingaveragesize As Long, ByVal sigmasize As Double, ByVal myflag As Long, ByVal sizeSeries As Long, ByRef Xdata As Double, ByRef Ydata As Double, ByVal sizeinputparameter As Long, ByRef averagePairs As Long, ByRef PositionsSize As Double, ByRef PnLSize As Double) As Double
Комментарии:
1. Пожалуйста, перенесите ваше объявление p / invoke.
2. Не уверен, что означает p / invoke, но вот как я объявляю функцию в VB
3. Я, очевидно, имел в виду «post» выше, а не port, но вы поняли идею
Ответ №1:
Declare Function MyFunction Lib "C:Devasdf.dll" (ByVal trailingaveragesize As Long, _
ByVal sigmasize As Double, ByVal myflag As Long, ByVal sizeSeries As Long,
ByRef Xdata As Double, ByRef Ydata As Double, ByVal sizeinputparameter As Long,
ByRef averagePairs As Long, ByRef PositionsSize As Double, ByRef PnLSize As Double) As Double
Объявление просто неверно, это напоминает объявление vb6. Int в коде C — это целое число в vb.net , не очень долго. Xdata и Ydata с высокой вероятностью будут массивами, а не двойными ссылками. Объявите их как ByVal Double() . Другие аргументы byref сложнее угадать.
Комментарии:
1. Вы абсолютно правы. Я переношу код, которому не менее 4-5 лет, с VBA на VB.net , и в этом-то и заключалась проблема. Спасибо
2. Знаете ли вы где-нибудь, где я могу найти диаграмму преобразования для VB.net ?
Ответ №2:
p-invoke — это вызов платформы, и именно так вы вызываете собственные API с помощью .NET. В настоящее время ваше объявление не настроено для передачи массивов, и это не должно выполняться по ссылке.
Попробуйте изменить ByRef на ByVal для ваших переменных массива и объявить их с помощью () для обозначения массива.
Комментарии:
1. Ага. Также мертв на деньги. Спасибо.
Ответ №3:
Ошибка заключается в том, что, хотя я объявлял переменную как тип long
, но она должна иметь тип integer
. Переменная rc
была ошибочно объявлена:
Вот код моей формы Form1
(в нем есть одна кнопка и одно текстовое поле):
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Вот код для Button.Click
(он инициализирует некоторые переменные, используемые для вызова функции в dll):
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim arg1 As String
Dim arg2 As String
Dim ret As String
Вот переменная rc, которую я объявил как long . Это должно быть целое число
Dim rc As long
ret = "123456789012345678901234567890123"
arg1 = "123456"
arg2 = "1234567890123456"
rc = myFunction(arg1, arg2, ret)
If (rc = 0) Then
TextBox1.Text = ret
Else
TextBox1.Text = "Result not OK"
End If
End Sub
End Class
myFunction
было объявлено как целое число в MyDLL:
extern __declspec(dllexport) int __stdcall myFunction(unsigned char * pszArg1, unsigned char * pszArg2, char * pszReturn)
Именно так я объявил MyFunction
в своем Visual Basic Express 2010:
Module Module1
Public Declare Function myFunction Lib "C:UsersmeMyProjectsmyDllbinDebugmyDll.dll" (ByVal Arg1 As String, ByVal Arg2 As String, ByVal ret As String) As Integer
End Module