Итак, у меня возникла старая проблема: «Я изменил свой код, и он не сработал, но потом я изменил его, и он все еще не работает». Мы работали с DLL как часть задания, и инструктор дал нам код для воспроизведения и записи звука, который должен был быть помещен в DLL, а затем использован в нашей собственной программе на C#. Вчера это работало нормально, но потом я пытался выяснить, был ли лишний код моего кода лишним, мне удалось его сломать.Win32 DLL в C# Program AccessViolationException
После вызова функции запуска initDialog
из моей основной программы теперь я получаю AccessViolationException
. Я хорошо знаю, что большую часть времени, когда вы получаете эту проблему, это потому, что вы пытаетесь использовать что-то, что осталось неинициализированным. Тем не менее, я не вижу ничего, что должно было бы вызвать эту проблему в моем коде, и отладчик действительно не дает мне никаких намеков относительно причины.
Я отправлю код для моей initDialog
функции и нижеуказанных объявлений переменных, и, если необходимо, я могу опубликовать больше кода позже. Идея заключается в том, что я создаю невидимое окно для обработки отправляемых сообщений, так что мне не нужно иметь дело с сообщениями на C#.
static WAVEFORMATEX waveform;
static PBYTE* pSaveBuffer;
static BOOL bRecording = FALSE, bPlaying = FALSE, bReverse = FALSE,
bPaused = FALSE, bEnding = FALSE, bTerminating = FALSE;
static DWORD dwDataLength, dwRepetitions = 1;
static HWAVEIN hWaveIn;
static HWAVEOUT hWaveOut;
static PBYTE pBuffer1, pBuffer2, pNewBuffer;
static PWAVEHDR pWaveHdr1, pWaveHdr2;
static HWND myHwnd;
static TCHAR szAppName[] = TEXT("Record/Play"),
static HINSTANCE hInst;
__declspec(dllexport) void CALLBACK initDialog() {
WNDCLASS wndclass;
MSG msg;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WinProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInst;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass)) {
MessageBox(NULL, TEXT("This program requires Windows 95/98/NT"),
szAppName, MB_ICONERROR);
return;
}
myHwnd = CreateWindow(szAppName, TEXT("Record/Play"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInst, NULL);
// Allocate memory for wave header
pWaveHdr1 = (PWAVEHDR)malloc(sizeof(WAVEHDR));
pWaveHdr2 = (PWAVEHDR)malloc(sizeof(WAVEHDR));
// Allocate memory for save buffer
*pSaveBuffer = (PBYTE)malloc(1);
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
В основной программе у меня есть этот код:
[DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
public static extern int initDialog();
public PlayForm()
{
InitializeComponent();
this.Show();
initDialog();//AccessViolationException???
}
Пара ключевых навыков, необходимых вам, чтобы научиться двигаться вперед. Прежде всего, это, безусловно, источник контроля, * очень важно, чтобы восстановить свою программу в ее первоначально работающее состояние. И вам нужно научиться отлаживать собственный код, чтобы вы могли видеть, какой оператор генерировал исключение. Все это хорошо видно в существующем Q + A на этом сайте. И, возможно, немного подумайте о мудрости выделения 1-байтового буфера сохранения и регистрации класса окна более одного раза. –
Помимо размышлений у Ганса, мне было интересно, что вы ожидаете от цикла с концом. – rene
@rene Цикл while предназначен для получения и обработки сообщений в WndProc. В этом случае я использую его для получения сообщений, относящихся к функциям воспроизведения и записи. – user2316502