我创建C ++中的DLL。 下面是一个例子:
namespace MathFuncs
{
class MyMathFuncs
{
public:
// Returns a + b
static __declspec(dllexport) double Add(double a, double b);
// Returns a - b
static __declspec(dllexport) double Subtract(double a, double b);
// Returns a * b
static __declspec(dllexport) double Multiply(double a, double b);
// Returns a / b
// Throws DivideByZeroException if b is 0
static __declspec(dllexport) double Divide(double a, double b);
};
}
所有方法都是静态的,也有很多与静态方法的局限性,所以我的问题是如何能够实现相同的不带静电的方法呢? 我总是必须DLL静态方法? 我要导入C#和iOS应用此DLL。
至于侧面说明我做了1实验前几天的MinGW / C ++至极可以澄清你。
我有发现在我的程序内存泄漏全局引用计数器,
class ReferenceCounter /** other implementations details are omitted.*/
{
public:
static int GlobalReferenceCounter;
//version 1
static int getReferenceCount1() { return GlobalReferenceCounter;}
//verison 2
static int getReferenceCount2(); //same code of version 1 but moved into .cpp file
};
当使用引用计数为DLL编译我的图书馆,则变量被复制,版本1编译成DLL,并且一个版本是在客户端代码编译。
当我问的参考计数的东西istances来自DLL的工厂方法,仅DLL内的参考计数器增加/减少。 当客户端代码,使用从参考计数器继承了它自己的类,则客户端参考计数器增加/减少。
因此,对于检查内存泄漏我必须在程序结束做
assert(ReferenceCounter.getReferenceCount1() == 0);
assert(ReferenceCoutner.getReferenceCount2() == 0);
这是因为在存储器的情况下泄漏的那些值中的一个将是大于0。如果第一个值大于1,则该内存泄漏是由未分配用户类引起的,如果第二值大于0,则内存泄漏是由库引起类。
请注意,如果泄漏是由未分配库的类造成的,这不一定是图书馆的一个错误,因为用户仍然能够泄漏的类,即使应该意味着缺乏在库设计的,因为理想的一切都很应退还在安全适当的智能指针。)
当然,你应该指定一个“GlobalReferenceCoutner”的文档中复制,否则一些不知情的用户可以只觉得2个干将是多余的,并会认为你做了一些错误。 (如果可能避免做这样的事情,是晦涩不清)
这也应该提醒大家,通过DLL的访问静态方法是非常不安全的。 例如,如果在我的课,我想只有1引用计数,而不是2我不得不这样做,对于授予安全:
class ReferenceCounter
{
public:
static int GlobalReferenceCounter;
static void duplicate() { increaseGlobalCounter(); }
static void release() { decreaseGlobalCounter(); }
static int getGlobalCounter() { return privateGetGlobalCounter(); }
private:
static increaseGlobalCounter(); // implementation into Cpp file
static decreaseGlobalCounter(); // implementation into Cpp file
static privateGetGlobalCounter(); // implementation into Cpp file
};
这样做,将授予你,相同的值跨DLL bounduaries,并在用户应用程序中使用。 所以不是有2个不同的变量,这里我们使用1个变量(可能是GlobalCounter仍然编译成可执行的用户,但没有人使用它删除“克隆效应”)
您必须使用全局,C风格的方法。 这样做的原因是这里描述 。
基本上它归结为:C函数很好地翻译成DLL导出,因为C是在语言功能方面“贴近地面”。 Ç转换更直接成机器代码。 C ++做了很多在编译器级别,给你很多的不能在C ++环境之外使用的功能。 出于这个原因,您的导出函数应遵循一个C风格,以跨越边界的DLL正常工作。 这意味着没有模板,没有内嵌代码,没有非POD类或结构。
考虑以下代码:
extern "C"
{
__declspec(dllexport) int GlobalFunc(int n)
{
return n;
}
namespace SomeNamespace
{
__declspec(dllexport) int NamespaceFunction(int n)
{
return n;
}
}
class MyClass
{
__declspec(dllexport) int ClassNonStatic(int n)
{
return n;
}
__declspec(dllexport) static int ClassStatic(int n)
{
return n;
}
};
}
这将导致以下DLL导出函数名:
?ClassNonStatic @ MyClass的@@ AAEHH @ Z
?ClassStatic @ MyClass的@@ CAHH @ Z
GlobalFunc
NamespaceFunction
与滑稽命名的是被比Visual Studio中内置C ++项目之外的任何本质上是不相容的。 这就是所谓的名字改编 ,嵌入某种类型的信息到这个名字本身作为一种解决方法,以导出函数我谈论的限制。 您可以在技术上外部使用这些功能,但它是脆弱的,依赖于具体的编译器行为的细微差别。
根据经验,在一个DLL导出函数的规则是:你可以在C这样做吗? 如果不能,那么几乎可以肯定你会造成问题。
这里注意,即使静态类的方法(本质上属于全球)仍然有名字改编,甚至extern "C"
。 但独立的功能,在没有名称重整命名空间的出口(尽管他们失去了命名空间范围)。
你可以开始明白为什么这个经验法则是有道理的。
如果要导出一个类,让我们遵循的经验法则,并设计了DLL接口,你会在做C.下面是一个例子。 让我们这个C ++类:
class Employee
{
private:
std::string firstName;
std::string lastName;
public:
void SetFirstName(std::string& s)
{
this->firstName = s;
}
void SetLastName(std::string& s)
{
this->lastName = s;
}
std::string GetFullName()
{
return this->firstName + " " + this->lastName;
}
};
你不能只拘泥于__declspec(dllexport)
这一点。 你必须为它提供一个C接口,和导出。 像这样:
extern "C"
{
__declspec(dllexport) Employee* employee_Construct()
{
return new Employee();
}
__declspec(dllexport) void employee_Free(Employee* e)
{
delete e;
}
__declspec(dllexport) void employee_SetFirstName(Employee* e, char* s)
{
e->SetFirstName(std::string(s));
}
__declspec(dllexport) void employee_SetLastName(Employee* e, char* s)
{
e->SetLastName(std::string(s));
}
__declspec(dllexport) int employee_GetFullName(Employee* e, char* buffer, int bufferLen)
{
std::string fullName = e->GetFullName();
if(buffer != 0)
strncpy(buffer, fullName.c_str(), bufferLen);
return fullName.length();
}
}
然后写在C#侧另一个小包装,并已成功地封这个类。
特别是用于编组的C#,另一种选择是提供一个COM接口,你的类,而不是C接口。 本质上,它是同样的事情,但也有很多辅助类和直接添加COM支持C ++类,而无需编写单独包装特殊的编译器的支持。 COM对象可直接由C#引用。
这不会帮助你与iOS虽然...