问题描述
我需要以以下形式将参数传递给不安全的 DllImported 函数:
I need to pass an argument to an unsafe DllImported function in the form of:
[DllImport("third_party.dll")]
private static extern unsafe int start(int argc, char** argv);
我假设它是一个字符串数组.但是,当我尝试执行以下操作时,出现无法从 string[] 转换为 char**"错误.我该如何让它发挥作用?谢谢.
I'm assuming it's an array of strings. However when I try to do the following, I get 'Cannot convert from string[] to char**' error. How do I go about getting this to work? Thanks.
string[] argv = new string[] { };
start(0, argv);
编辑 1:该问题被标记为重复,但查看可能的重复问题,我仍然不知道如何使其工作.
EDIT 1: The question was marked as duplicate, but looking at the possible duplicate question, I still do not see how to get this to work.
编辑 2: 进一步阐明问题和所需参数.它看起来像您的标准 argc/argv 参数(参数计数,然后是参数值).与启动 ac 程序的方式相同: int main(int argc, char** argv);
对于这个特殊问题,我根本不想传递任何参数(所以 count 为 0).
EDIT 2: To further clafiry the question and required parameters. It looks like your standard argc/argv parameters (parameter count, and then parameter values). The same way you would start a c program: int main(int argc, char** argv);
For this particular problem, I don't want to pass any arguments at all (so count is 0).
编辑 3:我从第 3 方库供应商处获得了更多信息.这里是:
EDIT 3: I got more information from the 3rd party library vendor. Here it is:
- 第一个参数是参数个数
第二个参数是一个以空字符结尾的字符串数组- 字符串是 ANSI 编码的
编辑 4:使用有效解决方案进行最终编辑(至少在我的情况下).我会把这个作为答案,但不能,因为这个问题被标记为重复.这是一个链接 回答一个对我帮助最大的问题.最后 dll 函数需要一个指向带有 ANSI 字符串的缓冲区的指针数组. 所以我的最终方法(基于链接的问题)如下.在内存中创建一个数组来保存指针,然后将每个字符串分配到内存中的其他位置,并在第一个指针数组中写入指向这些字符串的指针.此代码在生产中有效:
EDIT 4: Final edit with a working solution (at least in my case). I would make this the answer, but can't because this question is marked as a duplicate. Here's a link to a question that helped me the most. In the end the dll function expected an array of pointers to buffers with ANSI strings. So my final approach (based off the linked question), was as follows. Create an array in memory to hold the pointers, then allocate each string elsewhere in memory, and write pointers to those strings inside the first pointer array. This code works in production:
[DllImport("third_party.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int start(Int32 args, IntPtr argv);
public bool start(params string[] arguments)
{
int result;
if (arguments == null || arguments.Length == 0)
{
result = dll_system_startup(0, IntPtr.Zero);
}
else
{
List<IntPtr> allocatedMemory = new List<IntPtr>();
int sizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
IntPtr pointersToArguments = Marshal.AllocHGlobal(sizeOfIntPtr * arguments.Length);
for (int i = 0; i < arguments.Length; ++i)
{
IntPtr pointerToArgument = Marshal.StringToHGlobalAnsi(arguments[i]);
allocatedMemory.Add(pointerToArgument);
Marshal.WriteIntPtr(pointersToArguments, i * sizeOfIntPtr, pointerToArgument);
}
result = start(arguments.Length, pointersToArguments);
Marshal.FreeHGlobal(pointersToArguments);
foreach (IntPtr pointer in allocatedMemory)
{
Marshal.FreeHGlobal(pointer);
}
}
return result == 0;
}
推荐答案
我想你可能需要使用 Marshal.
I think you might need to use Marshal.
var a = (char*)Marshal.StringToCoTaskMemAuto("myString");
char** = &a;
这只是一个猜测,因为我没有接受 char** 的库,所以我无法尝试.
This is just a guess because I don't have a library that takes char** so I haven't been able to try it.
这篇关于如何使用 C# 获取 char**?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!