mathInit = (void* (*)())dlsym(handle, "CreateMathOperationInstance");
Здесь вы используете dlsym()
, чтобы найти этот символ в общей библиотеке.Это должна быть функция со связью C
, поскольку имя символа не искажено.Это важно, и имейте это в виду, когда вы смотрите на эту строку:
cout<< mathInstance->AddInt(num1, num2)<<endl;
Здесь AddInt
- это метод класса, на который указывает mathInstance
.Метод класса - это просто другая функция, за исключением того, что он всегда принимает скрытый указатель this
в качестве дополнительного аргумента.Это то, чем является метод класса, во многих словах, и это фактически имеет место с типичной реализацией C ++.C ++ технически фактически не требует, чтобы это имело место.Реализация C ++ может свободно реализовывать методы любым способом, который дает результаты, соответствующие спецификации C ++.Но, на практике, в типичной реализации C ++ это и есть метод класса.Функция с дополнительным параметром, на которую ссылаются как this
.
. Таким образом, приведенная выше строка в основном эквивалентна:
cout<< mathOperationClass::AddInt(mathInstance, num1, num2)<<endl;
Это в основном то, что происходитздесь, говоря очень свободно.
Этот метод / функция mathOperationClass::AddInt
, предположительно, находится в той же общей библиотеке, которую вы dlopen
-ed;и потому что вы dlopen
-эдировали его и на самом деле не ссылались на него, у вас есть ссылка на этот символ, и эта ссылка не может быть разрешена во время выполнения, следовательно, ваша неопределенная ошибка символа во время выполнения.
Единственное единственноеВы даже можете надеяться на то, что вызовите этот метод класса - если он вообще может быть вызван таким способом - также с помощью dlsym()
.Но для того, чтобы хоть малейшая молитва о том, чтобы на самом деле это удалось, нужно совершить целую кучу вещей.
Во-первых, вы должны выяснить фактический искаженный C ++.имя символа .Используя мой компилятор Linux x86_64 g ++ в качестве ссылки, искаженное имя для этого метода будет «_ZN18mathOperationClass6AddIntEii».Имея это в виду, вы можете использовать dlsym
, чтобы найти этот символ (или каково бы ни было действительное искаженное имя символа вашей реализации C ++ для этого метода) в вашей общей библиотеке.
И когда у вас есть этот символ, что теперь?Что ж, будем надеяться, что у вашей реализации C ++ действительно есть взломанный ABI C ++, где вы можете вызвать метод класса, явно передав ему дополнительный параметр this
, что-то вроде этого:
int (*addInt)(mathOperationClass *, int, int)=
reinterpret_cast<int (*)(mathOperationClass *, int, int)>
(dlsym(handle, "_ZN18mathOperationClass6AddIntEii"));
cout << (*addInt)(mathInstance, num1, num2) << endl;
Весь этоткарточный домик рухнет, если не будет подтверждено, что методы C ++ могут быть вызваны таким хакерским способом, в ABI вашей реализации C ++.Поскольку вы уже используете dlopen
(), вы уже находитесь в непереносимой территории, используя ресурсы, специфичные для реализации C ++, поэтому вы можете также выяснить, могут ли ваши методы C ++ вызываться таким образом.Если нет, вам придется выяснить, как они могут быть вызваны, используя простой указатель.
А теперь что-то совершенно другое ...
Сказав все вышеперечисленное:
Есть один способ избежать этого беспорядка: сделать этот метод класса методом виртуального класса.Методы виртуального класса отправляются через внутреннюю таблицу виртуальных функций.Поэтому попробуйте объявить этот метод AddInt
как метод виртуального класса и вызвать его как есть.Скорее всего, это будет работать в вашей реализации C ++, так как компилятор не будет выдавать, в данном случае, явную ссылку на символ для mathOperationClass::AddInt
.Он найдет метод с помощью таблицы виртуальных функций, которая незаметно присоединяется к каждому экземпляру объекта.
Конечно, вам также необходимо помнить, что такое виртуальные функции и их последствия.Но почти во всех случаях это довольно дешевый способ вызова методов классов, которые динамически загружаются из общей библиотеки.