Во-первых, я новичок в C ++ (почти неделю), так что простите, если это очевидно. Кроме того, я охотился через много сообщений с похожими проблемами. Либо мое понимание просто недостаточно развито, либо ни у кого не было соответствующей информации, чтобы помочь мне понять эту проблему.
В Metatrader 4 я пытаюсь выяснить, как передать структурную переменную в dll и изменить переменные, хранящиеся в указанной структуре. До сих пор я имел большой успех, даже когда имел дело со структурными массивами. Тогда я столкнулся с проблемой.
Я сузил проблему до использования строк. Если хотите, взгляните на следующий код, который я использовал, чтобы сосредоточиться на решении этой проблемы, и помогите мне понять, почему я продолжаю получать эту ошибку «Access error write to 0x00000000» всякий раз, когда я пытаюсь запустить скрипт в mt4 ,
Код MQL4:
struct Naming
{
string word;
} name;
#import "SampleDLLtest.dll"bool NameTest(Naming &name);
#import
int init() { return(0); }
int start()
{
Print("original name: ", name.word);
if( NameTest( name ) )
{
Print("new name: ", name.word);
}
//---
return(0);
}
Это соответствующий код DLL:
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
//---
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
//---
return(TRUE);
}
struct Naming
{
std::string n_name;
};
bool __stdcall NameTest(Naming *name)
{
name->n_name = "Captain Success";
return true;
}
Из документации mql4: http://docs.mql4.com/basis/preprosessor/import
Следующее нельзя использовать для параметров в импортируемых функциях:
- указатели (*);
- ссылки на объекты, которые содержат динамические массивы и / или указатели.
Классы, строковые массивы или сложные объекты, которые содержат строки и / или
динамические массивы любых типов не могут быть переданы в качестве параметра
функции импортированные из DLL.
Импортированная функция берет указатель, и это, очевидно, не поддерживается mql4.
Вам, вероятно, следует использовать массив символов фиксированного размера для передачи данных в и из dll:
лайк:
struct Naming {
char m_name[255];
}
Функция должна была бы принять ссылку на эту структуру (но это, вероятно, также не поддерживается) или принять структуру напрямую и вернуть структуру.
Naming NameTest(Naming name) {
strncpy(name.m_name, "New Content", sizeof(name.m_name) -1);
if (sizeof(name.m_name) > 0) {
name.m_name[sizeof(name)-1] = 0;
}
return name;
}
Вызов это будет выглядеть так:
name = NameTest(name);
Я знаю, что это немного странно, но я отвечаю на свой вопрос, потому что я выяснил, что происходит … по крайней мере, в основном.
Итак, вот сделка. Технически говоря, вы можете передать структуру, содержащую строку. Что вы не можете сделать, это отредактировать строку. В структуре нет автоматического преобразования строки в тип char []. Таким образом, когда dll пытается редактировать строку, она выбрасывает нарушение прав доступа, потому что строка на самом деле не является строкой в C ++, но является массивом символов, замаскированным под строку.
Тем не менее, я решил, как передать структуру, содержащую строку, и изменить значение в DLL. Вот как я это сделал.
—Начиная с кода mql4 —
Сначала я объявил структуру с символом [] вместо строки.
struct Naming
{
char word[65];
} name;
Затем я инициализировал char [] нулевым значением, проверил его, передал структуру и проверил, правильно ли установлено значение.
ArrayInitialize(name.word, '\0');
Print("original name: ", CharArrayToString(name.word));
if( NameTest( name ) )
{
Print("new name: ", CharArrayToString(name.word));
}
—Теперь к коду C ++ —
Я объявил ту же структуру.
struct Naming
{
char n_name[65];
};
Тогда функция. Сначала я должен был захватить строковый литерал во временном символе []. Я зациклил цикл for для распределения элементов в char [] в структуре. Проблема в том, что char [] из структуры не является const, а char temp [] есть. Я справился с этим, захватив каждый символ в переменную char, а затем сохранив значение этой переменной в struct char [].
bool __stdcall NameTest(Naming *name)
{
char temp[] = "Captain Success";
for (int i = 0; temp[i] != '\0'; i++)
{
char t = temp[i];
name->n_name[i] = t;
}
return true;
}
Этот код работает прекрасно.