未找到DLL的C#命名空间
好的,我会在这篇文章的开头说,在发布这篇文章之前,我在这里做了一个查找并阅读了很多类似的问题和答案 背景信息 使用Visual Studio Professional 2013 目标: 这个项目是我自己的娱乐,并试图学习尽可能多未找到DLL的C#命名空间,c#,dll,c++-cli,wrapper,C#,Dll,C++ Cli,Wrapper,好的,我会在这篇文章的开头说,在发布这篇文章之前,我在这里做了一个查找并阅读了很多类似的问题和答案 背景信息 使用Visual Studio Professional 2013 目标: 这个项目是我自己的娱乐,并试图学习尽可能多 我有一个名为BialTrut.h的本地C++头文件,它只是一个简单的数据结构,它使用递归逻辑来构建二进制搜索树。它本身运行得很好 我想在C#中构建一个GUI,它使用这个。(它不是真正有用或实用的,我只是选择它,因为我想这么做。此外,虽然二叉树类中的逻辑很复杂(ish),
我有一个名为BialTrut.h的本地C++头文件,它只是一个简单的数据结构,它使用递归逻辑来构建二进制搜索树。它本身运行得很好
我想在C#中构建一个GUI,它使用这个。(它不是真正有用或实用的,我只是选择它,因为我想这么做。此外,虽然二叉树类中的逻辑很复杂(ish),但我只需要调用2个方法,一个addNode方法和一个toString方法,它们返回最大深度和节点数) 我选择使用c++/cli包装器来实现这一点。一切似乎都进行得很顺利,构建成功,并且在我的项目的调试目录中创建了一个.dll文件 现在,我从事情的C端开始。我将.dll文件添加到引用中。然而,当我输入“usingfilename.dll”时,我得到一个错误,说“找不到类型或名称空间…” 重申一下,我做了一些调查。我发现(似乎在VS2010中)不同的目标框架可能会导致此错误。我检查了我的,两者的目标都是net4.5,所以这不是问题所在 下面是我的c++/cli包装器中的代码。也许这与使用模板有关?感谢您的帮助#pragma once
#include "D:\Schoolwork 2015\Test Projects\CPPtoC#WrapperTest\CPPLogic\CPPLogic\BinaryTree.h"
using namespace System;
namespace BinaryTreeWrapper {
template<class Data>
public ref class BinaryTreeWrapperClass
{
public:
BinaryTreeWrapperClass(){ tree = new BinaryTree(); }
~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
!BinaryTreeWrapperClass(){ delete tree; }
//methods
void wrapperAddNode(Data)
{
tree->addNode(Data);
}
std::string wrapperToString()
{
return tree->toString();
}
private:
BinaryTree* tree;
};
}
#pragma一次
#包括“D:\Schoolwork 2015\Test Projects\CPPtoC\WrapperTest\CPPLogic\CPPLogic\BinaryTree.h”
使用名称空间系统;
命名空间二进制树包装器{
模板
公共引用类BinaryTreeWrapperClass
{
公众:
BinaryTreeWrapperClass(){tree=new BinaryTree();}
~BinaryTreeWrapperClass(){this->!BinaryTreeWrapperClass();}
!BinaryTreeWrapperClass(){删除树;}
//方法
void wrapperAddNode(数据)
{
树->添加节点(数据);
}
std::string wrapperToString()
{
返回树->toString();
}
私人:
二叉树*tree;
};
}
错误的屏幕截图:
编辑
好吧,这里有件奇怪的事。。。我的原始文件使用新代码构建得很好,并生成了一个.dll文件。但是,我决定尝试一个新的项目,因为仍然找不到名称空间。在移动代码并尝试构建时,我遇到了4个错误:
错误1错误C2955:“BinaryTree”:使用类模板需要模板参数列表
错误2错误C2512:“BinaryTree”:没有合适的默认构造函数可用
错误3错误C2662:'void BinaryTree::addNode(Data)':无法将'this'指针从'BinaryTree'转换为'BinaryTree&'
错误4错误C2662:'std::string BinaryTree::toString(void)const':无法将'this'指针从'BinaryTree'转换为'const BinaryTree&'
我完全复制了代码,只是将名称空间更改为“TreeWrapper”,将类名更改为“TreeWrapperClass”
为了提供帮助,我加入了BinaryTree.h文件中的一个片段。还有很多定义“NODE”类的代码,但我不想把它弄得太乱
经过进一步调查,问题似乎出在使用“generic”上。如果我将其全部切换为“template”,它可以正常构建,但不能在C#中用作引用(获取名称空间错误)。我使用非常简单的方法构建了一个测试项目(没有模板)并且能够使用我在C#中制作的.dll包装器。所以问题在于模板和泛型
上次编辑
我发现,如果我更改代码以将模板初始化为“int”,它就可以正常工作,并且我可以在C#中使用它。例如:
...
BinaryTreeWrapperClass(){ tree = new BinaryTree<int>(); }
....
private:
BinaryTree<int>* tree;
。。。
BinaryTreeWrapperClass(){tree=new BinaryTree();}
....
私人:
二叉树*tree;
二叉树
template<class Data>
class BinaryTree
{
private:
Node<Data>* root;
unsigned int nNodes;
unsigned int maxDepth;
unsigned int currentDepth;
void traverse(Node<Data>*& node, Data data);
public:
BinaryTree();
~BinaryTree();
void addNode(Data);
std::string toString() const
{
std::stringstream sstrm;
sstrm << "\n\t"
<< "Max Depth: " << maxDepth << "\n"
<< "Number of Nodes: " << nNodes << "\n";
return sstrm.str(); // convert the stringstream to a string
}
};
template<class Data>
BinaryTree<Data>::BinaryTree() //constructor
{
//this->root = NULL;
this->root = new Node<Data>(); //we want root to point to a null node.
maxDepth = 0;
nNodes = 0;
}
template<class Data>
BinaryTree<Data>::~BinaryTree() //destructor
{
}
template<class Data>
void BinaryTree<Data>::addNode(Data data)
{
traverse(root, data); //call traverse to get to the node
//set currentDepth to 0
currentDepth = 0;
}
template<class Data>
void BinaryTree<Data>::traverse(Node<Data>*& node, Data data)
{
//increment current depth
currentDepth++;
if (node == NULL) //adds new node with data
{
node = new Node<Data>(data);
//increment nNode
nNodes++;
//increment maxDepth if current depth is greater
if (maxDepth < currentDepth)
{
maxDepth = currentDepth - 1; //currentDepth counts root as 1, even though its 0;
}
return;
}
else if (node->getData() >= data) //case for left, getData must be bigger. The rule is, if a number is equal to getData or greater, it is added to the left node
{
Node<Data>* temp = node->getLeftNode();
traverse(temp, data); //recursive call, going down left side of tree
node->setLeftNode(temp);
}
else if (node->getData() < data) //case for right, getData must be less
{
Node<Data>* temp = node->getRightNode();
traverse(temp, data);
node->setRightNode(temp);
}
return;
}
模板
类二叉树
{
私人:
节点*根;
无符号整数n节点;
无符号整数最大深度;
无符号int-currentDepth;
无效导线测量(节点*&节点,数据);
公众:
二叉树();
~BinaryTree();
void addNode(数据);
std::string toString()常量
{
std::stringstream sstrm;
sstrm getData()getRightNode();
导线测量(温度、数据);
节点->设置右侧节点(临时);
}
返回;
}
你声明的是“代码>模板”/Cuth>,但实际上并没有例示它。C++ + CLI模板就像C++模板——如果你不实例化它们,它们就不存在于编译单元之外。
您在这里寻找泛型(是的,C++/CLI既有模板也有泛型)。下面是如何在C++/CLI中声明泛型:
generic<class Data>
public ref class BinaryTreeWrapperClass
{
// ...
}
这不好,因为您返回的是std::string
-您不想从C#使用它,所以让我们返回System::string^
(使用):
请看……这里您必须执行一些真正的互操作。您希望将托管对象传递给本机对象以进行存储。GC将妨碍您
允许GC重新定位任何托管对象(将其移动到另一个内存位置),但您的本机代码对此一无所知。您需要锁定该对象,以便GC不会移动它
有几种方法可以做到这一点,我不知道BinaryTree::addNode
是什么样子,但我只假设它是BinaryTree::addNode(void*)
对于长期对象固定,可以使用
完整代码如下所示:
generic<class Data>
public ref class BinaryTreeWrapperClass
{
public:
BinaryTreeWrapperClass()
{
tree = new BinaryTree();
nodeHandles = gcnew System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>();
}
~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
!BinaryTreeWrapperClass()
{
delete tree;
for each (auto handle in nodeHandles)
handle.Free();
}
void wrapperAddNode(Data data)
{
auto handle = System::Runtime::InteropServices::GCHandle::Alloc(
safe_cast<System::Object^>(data),
System::Runtime::InteropServices::GCHandleType::Pinned);
nodeHandles->Add(handle);
tree->addNode(handle.AddrOfPinnedObject().ToPointer());
}
System::String^ wrapperToString()
{
return msclr::interop::marshal_as<System::String^>(tree->toString());
}
private:
BinaryTree* tree;
System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>^ nodeHandles;
};
通用
公共引用类BinaryTreeWrapperClass
{
公众:
BinaryTreeWrapperClass()
{
tree=新的二进制树();
nodeHandles=gcnew System::Collections::Generic::List();
}
~BinaryTreeWrapperClass(){this->!BinaryTreeWrapperClass();}
!BinaryTreeWrapperClass()
{
std::string wrapperToString()
{
return tree->toString();
}
#include <msclr/marshal_cppstd.h>
System::String^ wrapperToString()
{
return msclr::interop::marshal_as<System::String^>(tree->toString());
}
void wrapperAddNode(Data)
{
tree->addNode(Data);
}
generic<class Data>
public ref class BinaryTreeWrapperClass
{
public:
BinaryTreeWrapperClass()
{
tree = new BinaryTree();
nodeHandles = gcnew System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>();
}
~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
!BinaryTreeWrapperClass()
{
delete tree;
for each (auto handle in nodeHandles)
handle.Free();
}
void wrapperAddNode(Data data)
{
auto handle = System::Runtime::InteropServices::GCHandle::Alloc(
safe_cast<System::Object^>(data),
System::Runtime::InteropServices::GCHandleType::Pinned);
nodeHandles->Add(handle);
tree->addNode(handle.AddrOfPinnedObject().ToPointer());
}
System::String^ wrapperToString()
{
return msclr::interop::marshal_as<System::String^>(tree->toString());
}
private:
BinaryTree* tree;
System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>^ nodeHandles;
};