首页 > 解决方案 > 如何使用 C++ 导出动态链接库

问题描述

我正在 Visual Studio 2019 中构建一个 DLL 项目。

我将编写的数组库转换为 DLL,但它不起作用。

有两个编译错误:

C2254:假设函数定义了两次。

C2953:说数组类已经被声明了。

C2254 错误已通过在数组类声明中与函数声明同时定义函数来修复。所以代码是:

//ArrayLib.h
#ifdef ARRAYLIB_EXPORTS
#define ARRAYLIB_API __declspec(dllexport)
#else
#define ARRAYLIB_API __declspec(dllimport)
#endif

typedef signed long int Long;
template <typename T>

class Array {
public:
    Array(Long capacity = 256) {
        this->front = new T[capacity];
        this->capacity = capacity;
        this->length = 0;
    }

    Array(const Array& source) {
        this->front = new T[source.capacity];
        this->capacity = source.capacity;
        Long i = 0;
        while (i < source.length) {
            this->front[i] = source.front[i];
            i++;
        }
        this->length = source.length;
    }
    
    ~Array() {
        if (this->front != 0) {
            delete[] this->front;
        }
    }
    
    Long Store(Long index, T object) {
        this->front[index] = object;
        this->length++;

        return index;
    }
    
    Long Insert(Long index, T object) {
        T(*objects);
        Long i;
        Long j = 0;

        objects = new T[this->capacity + 1];
        i = 0;
        while (i < index) {
            objects[j] = this->front[i];
            j++;
            i++;
        }
        j++;
        while (i < this->length) {
            objects[j] = this->front[i];
            j++;
            i++;
        }
        if (this->front != 0) {
            delete[] this->front;
        }
        this->front = objects;
        this->capacity++;
        this->front[index] = object;
        this->length++;

        return index;
    }
    
    Long AppendFromFront(T object) {
        Long index = 0;
        T(*objects);
        Long i = 0;
        objects = new T[this->capacity + 1];
        while (i < this->length) {
            objects[i + 1] = this->front[i];
            i++;
        }

        if (this->front != 0) {
            delete[] this->front;
        }

        this->front = objects;
        this->capacity++;
        this->front[index] = object;
        this->length++;

        return index;
    }
    
    Long AppendFromRear(T object) {
        Long index;
        T(*objects);
        Long i = 0;
        objects = new T[this->capacity + 1];
        while (i < this->length) {
            objects[i] = this->front[i];
            i++;
        }
        if (this->front != 0) {
            delete[] this->front;
        }
        this->front = objects;
        this->capacity++;
        index = this->capacity - 1;
        this->front[index] = object;
        this->length++;

        return index;
    }
    
    Long Delete(Long index) {
        T(*objects) = 0;
        Long i = 0;
        if (this->capacity > 1) {
            objects = new T[this->capacity - 1];
        }
        while (i < index) {
            objects[i] = this->front[i];
            i++;
        }
        i = index + 1;
        while (i < this->length) {
            objects[i - 1] = this->front[i];
            i++;
        }
        if (this->front != 0) {
            delete[] this->front;
            this->front = 0;
        }
        if (this->capacity > 1) {
            this->front = objects;
        }

        this->capacity--;
        this->length--;
        index = -1;

        return index;
    }
    
    Long DeleteFromFront() {
        T(*objects) = 0;
        Long i = 1;
        if (this->capacity > 1) {
            objects = new T[this->capacity - 1];
        }
        while (i < this->length) {
            objects[i - 1] = this->front[i];
            i++;
        }
        if (this->front != 0) {
            delete[] this->front;
            this->front = 0;
        }

        if (this->capacity > 1) {
            this->front = objects;
        }
        this->capacity--;
        this->length--;
        return -1;
    }
    
    Long DeleteFromRear() {
        T(*objects) = 0;
        Long i = 0;

        if (this->capacity > 1)
        {
            objects = new T[this->capacity - 1];
        }

        while (i < this->length - 1)
        {
            objects[i] = this->front[i];
            i++;
        }

        if (this->capacity > 1)
        {
            this->front = objects;
        }

        this->capacity--;
        this->length--;

        return -1;
    }
    
    void Clear() {
        if (this->front != 0)
        {
            delete[] this->front;
            this->front = 0;
        }

        this->capacity = 0;
        this->length = 0;
    }
    
    Long Modify(Long index, T object) {
        this->front[index] = object;

        return index;
    }
    
    Long LinearSearchUnique(void *key, int(*compare)(void*, void*)) {
        Long index = -1;
        Long i = 0;

        while (i < this->length && compare(this->front + i, key) != 0)
        {
            i++;
        }

        if (i < this->length)
        {
            index = i;
        }

        return index;
    }
    
    void LinearSearchDuplicate(void *key, Long* (*indexes), Long *count, int(*compare)(void*, void*)) {
        Long i = 0;
        Long j = 0;
        *count = 0;

        *indexes = new Long[this->length];

        while (i < this->length)
        {
            if (compare(this->front + i, key) == 0)
            {
                (*indexes)[j] = i;
                j++;
                (*count)++;
            }

            i++;
        }
    }
    
    Long BinarySearchUnique(void *key, int(*compare)(void*, void*)) {
        Long index = -1;
        Long first = 0;
        Long last;
        Long mid;

        last = this->length - 1;
        mid = (first + last) / 2;
        while (first <= last && compare(this->front + mid, key) != 0)
        {
            if (compare(this->front + mid, key) < 0)
            {
                first = mid + 1;
            }
            else
            {
                last = mid - 1;
            }

            mid = (first + last) / 2;
        }

        if (first <= last)
        {
            index = mid;
        }

        return index;
    }
    
    void BinarySearchDuplicate(void *key, Long* (*indexes), Long *count, int(*compare)(void*, void*)) {
        Long first = 0;
        Long last;
        Long mid;
        Long i;
        Long j = 0;
        *count = 0;

        *indexes = new Long[this->length];
        last = this->length - 1;
        mid = (first + last) / 2;
        while (first <= last && compare(this->front + mid, key) != 0) {
            if (compare(this->front + mid, key) < 0) {
                first = mid + 1;
            }
            else {
                last = mid - 1;
            }
            mid = (first + last) / 2;
        }
        i = mid - 1;
        while (i >= first && compare(this->front + i, key) == 0) {
            i--;
        }
        first = i + 1;
        i = first;
        while (i <= last && compare(this->front + i, key) == 0) {
            (*indexes)[j] = i;
            j++;
            (*count)++;
            i++;
        }
    }
    
    void BubbleSort(int(*compare)(void*, void*)) {
        Long i = 0;
        Long j;
        T temp;
        Long check = 1;

        while (i < this->length - 1 && check == 1) {
            check = 0;
            j = 0;
            while (j < this->length - i - 1) {
                if (compare(this->front + j, this->front + (j + 1)) > 0) {
                    temp = this->front[j];
                    this->front[j] = this->front[j + 1];
                    this->front[j + 1] = temp;
                    check = 1;
                }
                j++;
            }
            i++;
        }
    }
    
    void SelectionSort(int(*compare)(void*, void*)) {
        Long i = 0;
        Long j;
        T min;
        Long minIndex;

        while (i < this->length - 1) {
            minIndex = i;
            min = this->front[minIndex];
            j = i + 1;
            while (j < this->length) {
                if (compare(&min, this->front + j) > 0) {
                    minIndex = j;
                    min = this->front[minIndex];
                }
                j++;
            }
            this->front[minIndex] = this->front[i];
            this->front[i] = min;
            i++;
        }
    }
    
    void InsertionSort(int(*compare)(void*, void*)) {
        Long i = 1;
        Long j;
        T temp;

        while (i < this->length) {
            temp = this->front[i];
            j = i - 1;
            while (j >= 0 && compare(this->front + j, &temp) > 0) {
                this->front[j + 1] = this->front[j];
                j--;
            }
            this->front[j + 1] = temp;
            i++;
        }
    }
    
    void Merge(const Array& one, const Array& other, int(*compare)(void*, void*)) {
        Long i = 0;
        Long j = 0;
        Long k = 0;

        if (this->front != 0) {
            delete[] this->front;
        }
        this->front = new T[one.length + other.length];
        this->capacity = one.length + other.length;
        this->length = 0;
        while (i < one.length && j < other.length) {
            if (compare(one.front + i, other.front + j) < 0) {
                this->front[k] = one.front[i];
                k++;
                this->length++;
                i++;
            }
            else {
                this->front[k] = other.front[j];
                k++;
                this->length++;
                j++;
            }
        }
        while (i < one.length) {
            this->front[k] = one.front[i];
            k++;
            this->length++;
            i++;
        }
        while (j < other.length) {
            this->front[k] = other.front[j];
            k++;
            this->length++;
            j++;
        }
    }
    
    T& GetAt(Long index) {
        return this->front[index];
    }
    
    T& operator [](Long index) {
        return this->front[index];
    }
    
    T* operator +(Long index) {
        return (this->front + index);
    }
    
    Array& operator =(const Array& source) {
        if (this->front != 0) {
            delete[] this->front;
        }
        this->front = new T[source.capacity];
        this->capacity = source.capacity;
        Long i = 0;
        while (i < source.length) {
            this->front[i] = source.front[i];
            i++;
        }
        this->length = source.length;

        return *this;
    }

    // 20160512 추가
    void Swap(Long toIndex, Long fromIndex) {
        T object = this->front[fromIndex];
        Long count;
        if (fromIndex > toIndex) {
            count = fromIndex - toIndex;
            memmove(this->front + toIndex + 1, this->front + toIndex, sizeof(T) * count);
        }
        else {
            count = toIndex - fromIndex;
            memmove(this->front + fromIndex, this->front + fromIndex + 1, sizeof(T) * count);
        }
        this->front[toIndex] = object;
    }

    Long GetCapacity() const {
        return this->capacity;
    }
    Long GetLength() const {
        return this->length;
    }

private:
    T(*front);
    Long capacity;
    Long length;
};

extern ARRAYLIB_API int nArrayLib;

ARRAYLIB_API int fnArrayLib(void);

这是cpp文件:

#include "ArrayLib.h"

ARRAYLIB_API int nArrayLib=0;

ARRAYLIB_API int fnArrayLib(void)
{
    return 0;
}

但是,我不确定如何修复 C2953 错误。

有办法吗?

还是我犯了另一个错误?

我是第一次构建 DLL。

我什至不知道为什么存在 nArrayLib 和 fnArrayLib。

更让我困惑的是,在简单的控制台应用程序或使用 GUI 构建器创建的应用程序中不会发生错误。

上述错误发生在我使用 MFC 的记事本应用程序中。

谢谢您的帮助。

标签: c++dll

解决方案


一种不完美但可行的方法是在声明后显式实例化模板:

template class Array<double>;
template class Array<int>;

进一步解释: exporting Template class in dll unresolved external

我准备了一个示例 VS 2017 项目: http ://www.mediafire.com/file/thxcz2dqplyqszb/ConsoleApplication5.zip/file


推荐阅读