我的任务是为.NET应用程序提供C ++代码库。 C ++代码在生产中已经使用了几年,并且可以正常运行。
我将C ++代码打包到一个dll中,并构建了一个基于C的API,以使其通过P / Invoke可用于.NET。
如果我通过基于C的测试应用程序测试API,那么一切都会按预期进行。如果我从C#应用程序测试API,则该应用程序将挂起。在调试过程中,我发现尽管执行了用于初始化C ++成员变量的代码,但该变量并未被初始化。
C ++类看起来像这样:
template<class T> class Product
{
enum product_status
{
alpha,
beta,
production
};
public:
explicit Product(T& src) : source(&src), status(alpha) { }
void bind(T& src) { source = &src; }
void reset()
{
source->reset();
status = alpha;
}
private:
Product(const Product<T>&);
const Product<T>& operator = (const Product<T>&);
T* source;
product_status status;
};
在导出的C方法中,这样声明了Product类型的变量:
void ProcessProduct(Type1* c1, Type2* c2)
{
//
// Do stuff
//
Product<Factory> p1(f1);
//
// Do stuff
//
}
执行了上面的行后,p1中的状态成员变量仍未初始化。仅当从.NET调用API时才发生这种情况,如果从C测试应用程序调用了API,则一切都将按预期方式初始化。
ProcessProduct方法在C#中这样声明:
[DllImport("product.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void ProcessProduct(IntPtr c1, IntPtr c2);
我的C ++知识是基础知识,因此我不确定自己缺少什么。我在Windows 10上使用Visual Studio 2019(16.6.3)。问题出现在Debug x86中,我没有在x64上对其进行测试。
答案 0 :(得分:1)
我终于设法找出问题并解决。
正如我所说的那样,C ++代码库已经稳定了几年,并且已经可以在生产环境中正常运行,因此我没有理由对其进行修改。
开发基于C的API之后,我使用C应用程序对其进行了测试,并且效果很好。之后,我开始使用C#应用程序,API开始崩溃或挂起。这让我感到困惑,因为API是通过C应用程序运行的,而不是通过C#运行的。事实是,在我开始处理C#部分之后,我没有再次测试C应用程序。
出现问题是因为我添加了“ pragma pack”指令以将某些结构从C映射到C#。我没有将其仅添加到这些结构中,而是将其添加到了一个包含在其他头文件之前的头文件中,并且该pragma指令弄乱了C ++代码库。说实话,Visual Studio生成了一些有关实用程序包不一致的警告,但我最初忽略了它们。
答案 1 :(得分:0)
某些样式可能无法解决问题,首先将product_status放在模板之外(其不依赖于T),第二个“类枚举”可能会消除歧义alpha(因此我无法分辨,bul可能存在其他称为alpha的东西在代码中的某处)
您可以“删除”复制构造函数和赋值运算符。
您可能正在创建一个称为“处理程序类”的东西,如果是这种情况,则如果该类是“产品”,则应从工厂函数中返回它,而不要指向该函数。尝试发现您是否可以使用shered_ptr或unique_ptr代替“ Product”