【发布时间】:2016-12-05 20:24:30
【问题描述】:
#ifdef SERVER_TCP_EXPORTS
class __declspec(dllexport) Sock_Server
#else
class __declspec(dllimport) Sock_Server
#endif
{
public:
int Server(const char* strErr,int bufSize);
...
}
cpp file
int Sock_Server::Server(const char* strErr,int bufSize)
{
// do something and assign the string to strErr
(say) strErr = "Hello World";
return -1;
}
in C#
[DllImport("Hello.dll", EntryPoint = "Server" CallingConvention = CallingConvention.StdCall)]
private extern static int Server(StringBuilder strErr, int bufSize);
public static int Connect(StringBuilder strErr, int bufSize)
{
int res = Server(strErr,bufSize); /// when the calls come here, strErr is empty
return res; // res has the value -1
}
private void Form1_Load(object sender, EventArgs e)
{
int res = 0;
int bufSize = 4096;
StringBuilder strErr = new StringBuilder(bufSize+1);
res = Connect(strErr, bufSize); //when the calls come here, strErr is empty
MessageBox.Show(strErr.ToString()); // it has the value -1
}
我不是 C# 人。我在发布之前做了一些阅读,并尝试了所有可能的组合,但由于某种原因它不起作用。我使用的是 Visual Studio 2013。我有几个 Q
[Q1] 当我做 MessageBox.Show(strErr.ToString());在我的 C# 中,它只打印一个空白字符串!如果有人可以帮助我,我将不胜感激,因为我对这一切都很陌生。
[Q2] 如果我给 EntryPoint ="Server" 我的代码不起作用。它抱怨,在 Hello.dll 中找不到服务器的入口点。所以,每次我必须使用 dumpbin.exe 在我的 dll 中找到确切的条目,然后准确地提供编译器为我创建的方式
[DllImport("Hello.dll", EntryPoint = "?Server@Sock_Server@@QAEHPBDH@Z" CallingConvention = CallingConvention.StdCall)]
有没有更好的方法来做到这一点。这使代码陷入困境
[Q3] 有没有办法调用 C++ 构造函数/析构函数。我确实需要调用它们。我通过其他方法调用了 C'tor,我知道这不是一个好主意。任何帮助将不胜感激.
谢谢。
【问题讨论】:
-
不要在 C++ 中分配字符串,(你只是在这里覆盖了提供的指针,任何调用函数都看不到)。将其复制到提供的
strErr缓冲区,而不是使用strcpy_s之类的东西。 -
要么你在某处丢失了
static,要么你真的试图将实例方法调用为静态方法,这是非常错误的,因为你会丢失this。除非您在命令行上覆盖它,否则调用约定不是stdcall,而是“C++ 特定调用”。而且 C# 在内部使用 UTF-16,所以char*也不起作用。而且你不能从 C# 实例化 C++ 对象,所以不用担心析构函数......这里有很多错误我不知道从哪里开始。我的建议是从一个小的工作样本重新开始。 -
它是一个C++类的实例函数。实例函数有一个额外的隐藏 this 参数。您的代码不会崩溃是因为您也没有编写有效的 C++ 代码,必须使用 strcpy_s() 复制字符串。你不能调用这样的函数,你没有很好的方法来为 this 创建正确的值。您必须将函数设为 static 或使用 C++/CLI 项目为类编写包装器。
标签: c# c++ c++11 visual-c++