Fuhrer_BMSTU
Fuhrer_BMSTU

Reputation: 35

The problem with explicitly linking the library

I have written a dynamic library libsort.so and connected it implicitly. Then I connected it explicitly through the keyboard. After compiling, I got the error undefined symbol. The file sort.cpp and sort.h are the sources of the dynamic library, example.cpp this is the program that I have connected the library to.

// sort.cpp
#include <bits/stdc++.h>
#include <iostream>

void merge(int array[], int const left, int const mid, int const right) {
  int const subArrayOne = mid - left + 1;
  int const subArrayTwo = right - mid;

  auto *leftArray = new int[subArrayOne], *rightArray = new int[subArrayTwo];

  for (auto i = 0; i < subArrayOne; i++)
    leftArray[i] = array[left + i];
  for (auto j = 0; j < subArrayTwo; j++)
    rightArray[j] = array[mid + 1 + j];

  auto indexOfSubArrayOne = 0, indexOfSubArrayTwo = 0;
  int indexOfMergedArray = left;

  while (indexOfSubArrayOne < subArrayOne && indexOfSubArrayTwo < subArrayTwo) {
    if (leftArray[indexOfSubArrayOne] <= rightArray[indexOfSubArrayTwo]) {
      array[indexOfMergedArray] = leftArray[indexOfSubArrayOne];
      indexOfSubArrayOne++;
    } else {
      array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo];
      indexOfSubArrayTwo++;
    }
    indexOfMergedArray++;
  }

  while (indexOfSubArrayOne < subArrayOne) {
    array[indexOfMergedArray] = leftArray[indexOfSubArrayOne];
    indexOfSubArrayOne++;
    indexOfMergedArray++;
  }

  while (indexOfSubArrayTwo < subArrayTwo) {
    array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo];
    indexOfSubArrayTwo++;
    indexOfMergedArray++;
  }
  delete[] leftArray;
  delete[] rightArray;
}

void mergeSort(int array[], int const begin, int const end) {
  if (begin >= end)
    return;

  int mid = begin + (end - begin) / 2;
  mergeSort(array, begin, mid);
  mergeSort(array, mid + 1, end);
  merge(array, begin, mid, end);
}

void printArray(int A[], int size) {
  for (int i = 0; i < size; i++)
    std::cout << A[i] << " ";
  std::cout << std::endl;
}

int rand_int(int min, int max) {
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<int> dist(min, max);
  return dist(gen);
}
// sort.h
void merge(int array[], int const left, int const mid, int const right);
void mergeSort(int array[], int const begin, int const end);
void printArray(int A[], int size);
int rand_int(int min, int max);
// example.cpp
#include <dlfcn.h>
#include <iostream>

int main(int argc, char *argv[]) {
  int (*rand)(int, int);
  void (*print_arr)(int[], int);
  void (*merge_s)(int[], int, int);

  void *ext_library = dlopen("/home/nikita/C++/shared/libsort.so", RTLD_LAZY);
  if (!ext_library) {
    std::cerr << "Error loading library: " << dlerror() << std::endl;
    return 1;
  }

  rand = (int (*)(int, int))dlsym(ext_library, "rand_int");
  print_arr = (void (*)(int[], int))dlsym(ext_library, "printArray");
  merge_s = (void (*)(int[], int, int))dlsym(ext_library, "mergeSort");

  if (!print_arr || !merge_s || !rand) {
    std::cerr << "Error loading symbols: " << dlerror() << std::endl;
    dlclose(ext_library);
    return 1;
  }

  int n = rand(5, 25);
  int *arr = new int[n];

  print_arr(arr, n);
  merge_s(arr, 0, n - 1);
  print_arr(arr, n);

  dlclose(ext_library);

  return 0;
}

example.cpp I compiled with the command g++ example.cpp -o example -ldl. I run it with the command ./example, then I got an error

Error loading symbols: /home/nikita/C++/shared/libsort.so: undefined symbol: mergeSort

I tried to change the compiler to clang, compilation is still successful, but when running ./example, the error remains the same.

Upvotes: 1

Views: 51

Answers (1)

Fuhrer_BMSTU
Fuhrer_BMSTU

Reputation: 35

I rewrote the library sources using extern C, after which everything worked fine.

// sort.cpp
#include <bits/stdc++.h>
#include <iostream>

#ifdef __cplusplus
extern "C" {
#endif

void merge(int array[], int const left, int const mid, int const right) {
  int const subArrayOne = mid - left + 1;
  int const subArrayTwo = right - mid;

  auto *leftArray = new int[subArrayOne], *rightArray = new int[subArrayTwo];

  for (auto i = 0; i < subArrayOne; i++)
    leftArray[i] = array[left + i];
  for (auto j = 0; j < subArrayTwo; j++)
    rightArray[j] = array[mid + 1 + j];

  auto indexOfSubArrayOne = 0, indexOfSubArrayTwo = 0;
  int indexOfMergedArray = left;

  while (indexOfSubArrayOne < subArrayOne && indexOfSubArrayTwo < subArrayTwo) {
    if (leftArray[indexOfSubArrayOne] <= rightArray[indexOfSubArrayTwo]) {
      array[indexOfMergedArray] = leftArray[indexOfSubArrayOne];
      indexOfSubArrayOne++;
    } else {
      array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo];
      indexOfSubArrayTwo++;
    }
    indexOfMergedArray++;
  }

  while (indexOfSubArrayOne < subArrayOne) {
    array[indexOfMergedArray] = leftArray[indexOfSubArrayOne];
    indexOfSubArrayOne++;
    indexOfMergedArray++;
  }

  while (indexOfSubArrayTwo < subArrayTwo) {
    array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo];
    indexOfSubArrayTwo++;
    indexOfMergedArray++;
  }
  delete[] leftArray;
  delete[] rightArray;
}

void mergeSort(int array[], int const begin, int const end) {
  if (begin >= end)
    return;

  int mid = begin + (end - begin) / 2;
  mergeSort(array, begin, mid);
  mergeSort(array, mid + 1, end);
  merge(array, begin, mid, end);
}

void printArray(int A[], int size) {
  for (int i = 0; i < size; i++)
    std::cout << A[i] << " ";
  std::cout << std::endl;
}

int rand_int(int min, int max) {
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<int> dist(min, max);
  return dist(gen);
}

#ifdef __cplusplus
}
#endif
// sort.h
#ifdef __cplusplus
extern "C" {
#endif

void merge(int array[], int const left, int const mid, int const right);
void mergeSort(int array[], int const begin, int const end);
void printArray(int A[], int size);
int rand_int(int min, int max);

#ifdef __cplusplus
}
#endif
// example.cpp
#include <dlfcn.h>
#include <iostream>
#include <ostream>

int main(int argc, char *argv[]) {
  int (*rand)(int, int);
  void (*print_arr)(int[], int);
  void (*merge_s)(int[], int, int);

  void *ext_library = dlopen("/home/nikita/C++/shared/libsort.so", RTLD_LAZY);
  if (!ext_library) {
    std::cerr << "Error loading library: " << dlerror() << std::endl;
    return 1;
  }

  rand = (int (*)(int, int))dlsym(ext_library, "rand_int");
  print_arr = (void (*)(int[], int))dlsym(ext_library, "printArray");
  merge_s = (void (*)(int[], int, int))dlsym(ext_library, "mergeSort");

  if (!print_arr || !merge_s || !rand) {
    std::cerr << "Error loading symbols: " << dlerror() << std::endl;
    dlclose(ext_library);
    return 1;
  }

  int n = rand(5, 25);
  int *arr = new int[n];

  for (int i = 0; i < n; i++)
    *(arr + i) = rand(-100, 100);

  std::cout << "Исходный массив: " << std::endl;
  print_arr(arr, n);
  merge_s(arr, 0, n - 1);
  std::cout << "Отсортированный масиив: " << std::endl;
  print_arr(arr, n);

  dlclose(ext_library);

  return 0;
}

Apparently, the function names have been subjected to the "name mangling" process by the C++ compiler. I fixed this error using extern C.

Upvotes: 1

Related Questions