简体   繁体   English

C#DllImport麻烦

[英]C# DllImport trouble

My question is a little general, so i'm not looking for an exact answer, but possibly some directions to look into that will help me... 我的问题有点笼统,所以我不是在寻找一个确切的答案,但可能有一些方向可以帮助我......

At my work place I program mostly in C#. 在我的工作场所,我主要用C#编程。 We have this 3rd party company we work with, that gave us a Native C++ dll that we need to use. 我们有这个与我们合作的第三方公司,它给了我们一个我们需要使用的Native C ++ dll。 Since the C++ method I needed wasn't exposed in a manner that was easy to reference from C#, I wrapped the dll in another Native C++ Dll. 由于我需要的C ++方法没有以易于从C#引用的方式公开,所以我将dll包装在另一个Native C ++ Dll中。

So now i have 2 Native C++ dlls, one wrapping the other. 所以现在我有2个Native C ++ dll,一个包装另一个。

I created a small C# console application that calls the method I created in C++. 我创建了一个小型C#控制台应用程序,它调用我在C ++中创建的方法。 My method signature looks like this : 我的方法签名如下所示:

[DllImport("HashMethodWrapper.dll")]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string CreateHash(
            string input,
            [MarshalAs(UnmanagedType.LPStr)]StringBuilder output);

In my console application, everything works fine, and i always receive the string im expecting in the result. 在我的控制台应用程序中,一切正常,我总是收到结果中期待的字符串。

But when I move it to a web service or a Web Application i created (since this is where i really need it), I see that the string im receiving is garbage and not even consistent. 但是当我将它移动到我创建的Web服务或Web应用程序时(因为这是我真正需要它的地方),我看到接收的字符串是垃圾而不是一致的。 It seems as if im getting just some reference to memory that is lost or something like that, but this is only a guess of mine... 好像我只是对丢失的内存或类似内容的一些引用,但这只是我的猜测......

I don't know why this happens, since in my console application everything works fine. 我不知道为什么会发生这种情况,因为在我的控制台应用程序中一切正常。

Does anyone have a direction that might help me ???... 有没有人有方向可以帮助我??? ...

Thanks in advance, gillyb 提前谢谢,吉利布

Edit : I thought it might have to do with some unpinned objects, so i tried calling the method in a fixed statement, something like : 编辑:我认为它可能与一些未固定的对象有关,所以我尝试在一个固定的语句中调用该方法,如:

unsafe public static string CreateHashWrap(string pass)
{
    String bb;
    StringBuilder outPass = new StringBuilder();
    fixed (char* resultStr = CreateHash(pass, outPass))
    {
        bb = new String(resultStr);
    }
    return bb;
}

...but this still didn't do it for me. ......但这仍然没有为我做。 Is this the right way to pin objects ? 这是固定物体的正确方法吗?

2nd Edit : The method signature in C++ looks like this : 第二次编辑: C ++中的方法签名如下所示:

extern "C" __declspec(dllexport) char *CreateRsaHash(char *inputPass, char *hashPass);

3rd Edit : I changed the signature of the method to be 3rd Edit:我改变了方法的签名

extern "C" __declspec(dllexport) bool CreateRsaHash(char *inputPass, char *hashPass);

and the return value im looking for is placed in the *hashPass parameter. 并且我要查找的返回值放在*hashPass参数中。

Now, I created a simple Console application to test it. 现在,我创建了一个简单的控制台应用程序来测试它。 When insert the DllImport in my main class, and directly call the method everything works great, but when I move the DllImport and wrap the method in a different class and call that class from the Console 'Main' method, I get a StackOverflow exception! 在我的主类中插入DllImport,并直接调用该方法时,一切都很好,但是当我移动DllImport并将该方法包装在另一个类中并从Console'Main'方法调用该类时,我得到一个StackOverflow异常!

Anyone got any ideas why this is happening ?? 有人知道为什么会这样吗?

在将StringBuilder传递给interop方法之前,请尝试指定它的容量

It's really hard to know from the sparse information but if I had to guess I would say you need to make sure you're pinning the output object. 从稀疏的信息中很难知道但是如果我不得不猜测我会说你需要确保你固定输出对象。 Also I would probably change the output parameter to some other type, it seems pretty strange that StringBuilder works at all frankly. 另外我可能会将输出参数更改为其他类型,看起来很奇怪StringBuilder可以坦率地工作。

I do know that if you allocate an object, it will get a pointer but that doesn't mean that it won't move. 我知道如果你分配一个对象,它会得到一个指针,但这并不意味着它不会移动。 So if you try to pass a pointer to a managed object into an unmanaged environment you need to make sure you tell the GC to "pin" the memory so it doesn't get moved out from under you. 因此,如果您尝试将指向托管对象的指针传递到非托管环境中,则需要确保告诉GC“固定”内存,以便它不会从您的下方移出。

Here is a really rough version of what I mean by pinning: 这是一个非常粗略的版本,我的意思是固定:

string input = "...";
StringBuilder output = new StringBuilder();
var handle = System.Runtime.InteropServices.GCHandle.Alloc(output, GCHandleType.Pinned);
try
{
    CreateHash(input, output);
}
finally
{
    handle.Free();
}

I would consider to warp inside a C# shared assembly/dll instead of a c++ dll and then try to get your console application to work with the dll. 我会考虑在C#shared assembly / dll而不是c ++ dll中进行扭曲,然后尝试让你的控制台应用程序与dll一起工作。 It is good practice to wrap external dependencies this way anyway. 无论如何,最好以这种方式包装外部依赖项。
Otherwise some traditional issues are 32 vs 64 bit, the load path to the shared library. 否则,一些传统问题是32比64位,即共享库的加载路径。 Is it really only a string or something more complex? 它真的只是一个字符串或更复杂的东西吗?

I found the solution to my problem, and now i feel kinda (if not really!) stupid... :-| 我找到了我的问题的解决方案,现在我感觉有点(如果不是真的!)愚蠢...: - |

I used the LoadLibrary() method in C++ to dynamically invoke a method from the other native dll. 我在C ++中使用LoadLibrary()方法从其他本机dll动态调用方法。 The problem was that I didn't give the method any path, and just the dll filename. 问题是我没有给方法任何路径,只有dll文件名。 In .net, it would've searched in the current folder, but seems like in native code this doesn't work this way. 在.net中,它会在当前文件夹中搜索,但在本机代码中似乎不会以这种方式工作。

The bigger problem in my programming practices is obviously the fact that i didn't fully cover error handling in my native C++ dll! 我的编程实践中的更大问题显然是我没有完全覆盖我的本机C ++ DLL中的错误处理!

All the asnwers I received on this page weren't for nothing though... 我在这个页面收到的所有收据都不是没有...

Once I found out that i had problem with the directory path, I ran into different exceptions about trying to access corrupt memory, etc. And then I needed to create pinned objects, and declare a size for my StringBuilder object. 一旦我发现我的目录路径有问题,我遇到了关于尝试访问损坏的内存等的不同异常。然后我需要创建固定对象,并为我的StringBuilder对象声明一个大小。

Thanks to everyone for your help!! 感谢大家的帮助!!

:) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM