Создание MFC DLL из кода C / C ++ (VS 2010) для использования веб-службой C # WCF - PullRequest
0 голосов
/ 24 марта 2012

У меня есть сторонний компонент, написанный на C / C ++ (на VS 2010), который можно загрузить здесь .

Этот компонент принимает 3 параметра в качестве входных данных (имя файла и два числа) и выводит результат в консоль, а затем выводит файл.

Я использовал Process и ProcessStartInfo в C #WinForm проект для использования этого компонента, который работает нормально.Однако теперь я хочу использовать это в службе WCF C # RESTful, и в этом случае решение, которое я думал с WinForm, не будет работать.Было предложено вместо этого преобразовать это в MFC DLL и затем использовать InterOp для вызова неуправляемой DLL через мой веб-сервис на C # (другие предложения приветствуются).

К сожалению, я понятия не имею, как это сделатьи мои знания по C / C ++ довольно средние.Итак, мой вопрос: как мне создать DLL из этого компонента, который принимает эти 3 параметра (взятые из main ()):

    cin >> fname;
    cin  >> minA;
    cin  >> minO;

, затем делает все необходимые вычисления и возвращает это (снова взятоfrom main ()):

cout << "\nNumber is: " << num;

(и, очевидно, по-прежнему выводить файл, который он должен выводить)?

Любая помощь будет высоко оценена.Заранее спасибо!

ОБНОВЛЕНИЕ: Для справки, вот моя реализация WinForm, упомянутая выше.

    ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
    Process cmdProcess = new Process();
    BackgroundWorker BWorker = new BackgroundWorker();

//is able to report progress
    BWorker.WorkerReportsProgress = true;
    //is able to be cancelled
    BWorker.WorkerSupportsCancellation = true;
    //attach events
    BWorker.DoWork += worker_DoWork;
    BWorker.RunWorkerCompleted += worker_RunWorkerCompleted;
    BWorker.RunWorkerAsync();

  private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        if (firstTimeLoaded)
        {
            cmdStartInfo.FileName = Path.GetFullPath("../../Resources/thirdparty.exe");
            cmdStartInfo.WorkingDirectory = Path.GetFullPath("../../Resources/");
            cmdStartInfo.RedirectStandardOutput = true;
            cmdStartInfo.RedirectStandardError = true;
            cmdStartInfo.RedirectStandardInput = true;
            cmdStartInfo.UseShellExecute = false;
            cmdStartInfo.CreateNoWindow = true;
            cmdProcess.StartInfo = cmdStartInfo;
            cmdProcess.SynchronizingObject = this;
            cmdProcess.ErrorDataReceived += cmd_Error;
            cmdProcess.Exited += cmd_Exited;
            cmdProcess.EnableRaisingEvents = true;
            cmdProcess.Start();
            cmdProcess.BeginErrorReadLine();
            firstTimeLoaded = false;
        }
        while (!cmdProcess.HasExited)
        {
            if (use)
            {
                if (BWorker.CancellationPending)
                {
                    e.Cancel = true;
                }
                StringBuilder builder = new StringBuilder();
                //read unbuffered output
                while (cmdProcess.StandardOutput.Peek() != -1)
                {
                    char inputChar = (char)cmdProcess.StandardOutput.Read();
                    if (inputChar != '\r' && inputChar != '\n')
                    {
                        builder.Append(inputChar);
                    }
                    if (inputChar == '\n')
                    {
                        break;
                    }
                }
                if (cmdProcess.StandardOutput.Peek() == -1)
                {
                    cmdProcess.StandardOutput.DiscardBufferedData();
                }
                //process the output
                string output = builder.ToString();
                //determine appropriate action
                switch (output)
                {
                    case "Enter file name: ":
                        cmdProcess.StandardInput.WriteLine(textBox1.Text);
                        break;
                    case "Enter minimum size of A: ":
                        cmdProcess.StandardInput.WriteLine(textBox2.Text);
                        break;
                    case "Enter minimum size of O: ":
                        cmdProcess.StandardInput.WriteLine(textBox3.Text);
                        break;
                }
                if (output.Contains("Number: "))
                {
                    MessageBox.Show("Number is: " + output.Substring(output.LastIndexOf(" ") + 1));
                    use = false;
                }         

            }

        }
    }

1 Ответ

1 голос
/ 25 марта 2012

Давайте попробуем.

  1. В VS2010 создайте проект Win32 под Visual C ++ / Win32.Для этого назовите его MyWin32Lib.
  2. Добавьте файл thirdparty.cpp в проект и скомпилируйте.Вы должны получить некоторые предупреждения, но это нормально.
  3. Создайте новый заголовочный файл с именем thirdparty.h, чтобы мы могли экспортировать подпись функции.
  4. В файле Thirdparty.h выполните:

    #pragma once
    // This will be the interface for third party file
    int concepts(char* szFileName, int nMinIntent, int nMinExtent);
    
  5. В файле Thirdparty.cpp добавьте #include "stdafx.h" прямо перед #include

  6. Изменить основнойподпись функции, совпадающая с подписью в заголовке:

    //int main()
    // Instead of getting input from console, we're passing it the values
    int concepts(char* szFileName, int nMinIntent, int nMinExtent)
    
  7. Закомментируйте все входные запросы и просто скопируйте аргументы в локальные переменные:

    //cout << "\n\n***** In-Close 3.0 Concept Miner *****";
    //cout << "\n\nEnter cxt file name including extension: ";
    //cin >> fname;
    //cout << "\nEnter minimum size of intent (no. attributes): ";
    //cin  >> minIn;
    //cout << "\nEnter minimum size of extent (no. objects): ";
    //cin  >> minEx;
    
    strcpy_s(fname, _countof(fname), szFileName);
    minIn = nMinIntent;
    minEx = nMinExtent;
    
  8. Comment out cout << "\ nNumber ... (это больше не требуется) </p>

  9. В конце функции выполните:

    break;
    }
    
    //cout << "\n\nHit <enter> to finish";
    //while ( !_kbhit());
    
      return numcons;
    }
    

Я не знаю, почему есть какое-то время (1), потому что нет никакого способа выбраться из этого, но предположим, что мы сделаем это только один раз.

  1. Убедитесь, что вы правильно скомпилировали.
  2. Создайте новый файл CPP, назовите его «Concepts.cpp»
  3. В Concepts.cpp введите:

    #include "stdafx.h"
    #include "thirdparty.h"
    
    extern "C"
    {
        __declspec(dllexport) int GetConcepts(char* szFileName, int nMinIntent, int nMinExtent)
        {
          return concepts(szFileName, nMinIntent, nMinExtent);
        }
    }
    

* Теперь у вас должен быть Win32DLL, которая выполняет работу, используя вместо этого аргументы.

  1. Создайте проект библиотеки классов C #.
  2. Создайте класс C # с именем "Concepts.cs"
  3. В этом классе введите:

    public class Concepts
    {
      // Link to the Win32 library through InterOp
      [DllImport("MyWin32Lib.dll")]
      public static extern int GetConcepts(
        [MarshalAs( UnmanagedType.LPStr )] string fileName, int minIntent, int minExtent );
    }
    

* Вы должны упорядочить ввод имени файла как ANSI, так как это то, что использует Thirdparty.cpp.

Я думаю, я получил всеэтогоТеперь вы можете ссылаться на свою библиотеку C # из веб-службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...