【问题标题】:Data values in the parameters are beeing copied to the other parameters c++, c#参数中的数据值被复制到其他参数 c++, c#
【发布时间】:2012-06-04 13:35:08
【问题描述】:

在 c++ 中,我要导出的方法是:

__declspec(dllexport) int __thiscall A::check(char *x,char *y,char *z)
{
  temp=new B(x,y,z);
}

在 c# 中我像这样导入这个方法:

[DllImport("IDLL.dll", CallingConvention=CallingConvention.ThisCall, ExactSpelling = true, EntryPoint = "check")]
    public static extern int check(string x, string y, string z);

我在 c# 中像这样调用这个方法并传递值:

public int temp()
{
  string x="sdf";
  string y="dfggh";
  string z="vbnfg";
  int t;

  t=Class1.check(x,y,z);
  return t;
}

问题是,当我调试本机代码时,我看到参数 x、y、z 的值为 sdf、dfggh、vbnfg,并且在它们到达 c++ dll 时甚至在它进入本机 c++ 之前就被更改了dll方法。

x=dfggh,y=vbnfg,z=null value

并且给我一个错误,说空指针值被传递给函数。谁能帮我解决这个奇怪的问题。

【问题讨论】:

  • 刚刚看过我几年前写的一些代码。尝试在每个 string 参数之前添加 [MarshalAs(UnmanagedType.LPStr)]UnmanagedType.LPStr 表示 指向以空字符结尾的 ANSI 字符数组的指针
  • 是不是只有z变成了null,x和y都没有问题?如果是,则检查 B 的 ctor 中修改 z 的那些部分。
  • @kol --- 甚至在进入构造函数 B 本身之前,值正在被更改。
  • @hmjd ---我尝试了你提到的但有同样的问题。

标签: c# c++ visual-c++ c#-4.0


【解决方案1】:

看起来您的本机方法是一个实例(与静态)方法。我猜你的第一个参数会以某种方式映射到“this”。

这是一个例子:

#include <fstream>
using namespace std;

class A
{
public:
__declspec(dllexport) static int __stdcall check(char *x,char *y,char *z)
{
    ofstream f;
    f.open("c:\\temp\\test.txt");
    f<<x<<endl;
    f<<y<<endl;
    f<<z<<endl;
    return 0;

    }

__declspec(dllexport) int __thiscall checkInst(char *x,char *y,char *z)
{
    ofstream f;
    f.open("c:\\temp\\testInst.txt");
    f<<x<<endl;
    f<<y<<endl;
    f<<z<<endl;
    return 0;

    }
};

看到第一个的static关键字了吗?

Imports(因为我很懒,所以我用了乱七八糟的名字):

[DllImport("TestDLL.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "?check@A@@SGHPAD00@Z")]
    public static extern int check(string x, string y, string z);

    [DllImport("TestDLL.dll", CallingConvention = CallingConvention.ThisCall, ExactSpelling = true, EntryPoint = "?checkInst@A@@QAEHPAD00@Z")]
    public static extern int checkInst(IntPtr theObject, string x, string y, string z);

这使它像这样工作:

check("x", "yy", "zzz");

实例方法需要一个 IntPtr

IntPtr obj = IntPtr.Zero;
checkInst(obj, "1", "12", "123");

而我的 test.txt 的内容是:

x
yy
zzz

和 testInst.txt

1
12
123

【讨论】:

  • “本机方法是实例(相对于静态)方法”是什么意思
  • A::check 看起来像是 A 类上的非静态(需要对象)方法,您需要导出静态方法或函数才能使 P/Invoke 工作
  • 我认为不需要静态方法才能使用 pinvoke。因此,由于该方法是 __stdcall 类型,所以它需要是静态的?
  • 检查这个答案stackoverflow.com/a/2354222/842543 您不能只从 C# 静态调用一个方法 - 它需要另一端的对象?谁来建造它?
  • 好的,我在这里感到困惑,您能否提供一个示例代码来说明您的观点。基本示例就足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
相关资源
最近更新 更多