【问题标题】:Problems manipulating strings through a stdcall to a dll通过对 dll 的 stdcall 操作字符串的问题
【发布时间】:2011-11-16 01:37:39
【问题描述】:

我需要创建一个 C++ dll,它将通过 stdcall 从另一个程序中调用。

需要什么:调用程序将一个字符串数组传递给 dll,而 dll 应该更改数组中的字符串值。然后调用程序将继续使用来自 dll 的这些字符串值。

我做了一个简单的测试项目,我显然遗漏了一些东西......

这是我的测试 C++ dll:

#ifndef _DLL_H_
#define _DLL_H_

#include <string>
#include <iostream>

struct strStruct
{
    int len;
    char* string;
};

__declspec (dllexport) int __stdcall TestFunction(strStruct* s)
{
   std::cout << "Just got in dll" << std::endl;

   std::cout << s[0].string << std::endl;
   //////std::cout << s[1].string << std::endl;

   /*
   char str1[] = "foo";
   strcpy(s[0].string, str1);
   s[0].len = 3;

   char str2[] = "foobar";
   strcpy(s[1].string, str2);
   s[1].len = 6;
   */

   //std::cout << s[0].string << std::endl;
   //std::cout << s[1].string << std::endl;

   std::cout << "Getting out of dll" << std::endl;

   return 1;
}

#endif

这是一个简单的 C# 程序,我用它来测试我的测试 dll:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Runtime.InteropServices;

 namespace TestStr
 {
     class Program
     {
         [DllImport("TestStrLib.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
         public static extern int TestFunction(string[] s);

         static void Main(string[] args)
         {
             string[] test = new string[2] { "a1a1a1a1a1", "b2b2b2b2b2" };

             Console.WriteLine(test[0]);
             Console.WriteLine(test[1]);

             TestFunction(test);

             Console.WriteLine(test[0]);
             Console.WriteLine(test[1]);

             Console.ReadLine();
         }
     }
 }

这是产生的输出:

a1a1a1a1a1
b2b2b2b2b2
Just got in dll
b2b2b2b2b2
Getting out of dll
a1a1a1a1a1
b2b2b2b2b2

我有一些问题:

1) 为什么输出的是数组的第二个位置而不是第一个位置的元素??

2) 如果我取消注释 dll 文件中用 ////// 注释的行,程序会崩溃。为什么?

3) 显然,我想在 dll(/* */ 中的部分)中做比现在做的更多的事情,但我被前两个问题阻止了......

感谢大家的帮助

【问题讨论】:

    标签: c++ string dll stdcall


    【解决方案1】:

    您不能将 string[] 编组为原生 struct

        [DllImport("TestStrLib.dll", CharSet = CharSet.Ansi, 
                 CallingConvention = CallingConvention.StdCall)]
                 public static extern int TestFunction(string[] s);
    
          struct strStruct
            {
                int len;
                char* string;
            }
    
        __declspec (dllexport) int __stdcall TestFunction(strStruct* s);
    

    请阅读http://msdn.microsoft.com/en-us/library/fzhhdwae.aspx了解各种类型的编组。

    在 C# 中

        [DllImport( "TestStrLib.dll" )]
        public static extern int TestFunction([In, Out] string[] stringArray
        , int size);
    

    在 C++ 中

    __declspec(dllexport) int TestFunction( char* ppStrArray[], int size)
       {
           return 0;
       }
    

    【讨论】:

    • 谢谢,我从另一个工作程序中获取了该模式...我不明白为什么它不适用于我的测试,但是您建议改用什么?
    • 事实上,真正的调用者不会是 C# 程序,而是 MQL4 程序...请参阅 forum.mql4.com/35537,这是我获得将字符串传递给 c++ dll 的当前实现的地方struct 并且它正在根据其他人工作
    • 我不确定 MQL4 是否......但对于 C#,我已经给了你正确的答案
    • 我使它部分与您的答案一起工作,但是由于我传递的是两个字符串而不是单个字符串的数组,因此我使用了 public static extern int TestFunction(strStruct[] p);而不是将 ref 传递给结构
    • 我取消了 dll 中 /* */ 代码的注释,现在它正在正确更改字符串值(在 strcpy 之后使用 cout 检查,在 dll 中)。但是,C# 程序中的最后 2 个 Console.WriteLine(在 dll 调用之后)输出与调用之前相同的字符串值(a1a1a1a1a1 和 b2b2b2b2b2),所以就像调用者不知道从 dll 所做的更改一样?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    相关资源
    最近更新 更多