質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.02%

  • C++

    2930questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • F#

    7questions

    F#は、MicroSoftが開発した.NET Framework 向けのマルチパラダイムプログラミング言語です。 Visual Studio 2010 より標準搭載されました。

C++のプログラムからF#の関数の呼び出し方

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 268

junya_t

score 3

前提・実現したいこと

C++のプログラムからF#の関数を呼び出したいです。

発生している問題・エラーメッセージ

C++のプログラムでF#の関数を呼び出したいのですが,やり方が分かりません。

該当のソースコード

ここにご自身が実行したソースコードを書いてください

試したこと

F# のソースファイルで関数の宣言部分でextern "F" や__declspec(dllexport)を、
C++で[<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]を記述してみましたがダメでした。

補足情報(言語/FW/ツール等のバージョンなど)

開発環境:Visual Studio 2013 Update4
F# 3.1
フレームワーク:.Net Framework 4.5.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yohhoy

    2017/09/29 23:12

    "C++"というのはunmanagedなnative C++を指していますか?もしくは.NET C++/CLIですか?

    キャンセル

  • junya_t

    2017/10/02 10:03

    .Net C++/CLI(visual C++)を使っています。曖昧な部分があり、すみません。

    キャンセル

回答 1

checkベストアンサー

+3

C++からF#の関数を呼ぶのは不可能ではないはずですが、現状、かなり難しいようです。

お試しになったやり方は F#からC++/C言語の関数を呼ぶP/Invokeの方法です。
(ただし、それでも不完全です)目的の再確認になりますが、呼び出す側の言語としては
.NET Framework用のC++/CLIではなく、ネイティブのC++ からF#の関数を呼ぶ方法、
で正しいでしょうか。

F# はご存知のように、.NET Framework上で稼動する実行ファイルを作成する言語です。
C++で作成したネイティブの実行コードからは、.NET Framework上で動作するコードに
アクセスする為、.NET Frameworkとは別の、WindowsのCOMインターフェースを
経由する必要があります。

以下は、「C++からC#のDLLを呼ぶ方法」を紹介された、大変参考になる情報へのリンクです。
C++からC#のDLLを呼ぶ方法

大筋においてこちらで紹介されている方法でC#のコード、ひいては.NET Framework用の
言語で提供される関数に、全部とはいかず、制限付きながらもアクセスできるはずですが、
Visual Studio 2015(※1)でのF#のプロジェクトの設定画面をみると、ビルドで造られる
アセンブリDLLを「COMの相互参照を可能」とし、Windowsに登録する方法が見当たりませんでした。

別途コマンドラインからセットする方法もありそうなのですが、正しく動作する例は未確認です。
※1 質問者様の使われているVisual Studioは2013ですが、ほぼ同じと思われます。

現状、F#の関数を別のC++な言語から利用する手としてより簡単なのは

  1. F#の関数を C++ではなく、C++/CLIから利用する。
  2. F#の関数を C#から利用する。C#とC++はCOMを経由して使う。

かと考えられます。ソフトの規模にもよりますが、そうまで苦労してネイティブ用C++
からF#の関数を呼べるようにするべきか、再考の余地があるかと思います。

尚、上記とは反対にF#からC++の関数を呼ぶのは正しくP/Invoke 用の設定さえすれば、はるかに簡単です。

参考になれば幸いです。

 [追記] C++/CLIのコードから F#のものを呼び出す

Visual Studio 2012でできました

前提がC++/CLI と言うことでしたので、改めて確認しました。
遅くなりましたが、試して確証を得た範囲でお答えします。

私の方で先に提示させていただいた代案

  1. F#の関数を C++ではなく、C++/CLIから利用する。

ですが、Visual Studio のバージョンによってはビルドできず、確認できませんでした。
OKだったのは Visual Studio 2012 ですので、そちらで紹介します。
VS2015ではNGでしたが、いろいろいじって環境が変わったせいがあるかもしれません。
(原因は追究できていません)
VS2013はインストールしていないので未確認です。

VS2012で試した限り、基本的には以下のプロジェクト作成の流れで
C++/CLIからF#のメソッドを呼べました。

  1. F#のプロジェクトを「ライブラリ」で作成する。(.NETアセンブリ DLL)

  2. 同じソリューションの管理下で、C+++/CLIのプロジェクトを作る。
    (「コンソールアプリ」で試しました)

  3. C++/CLIのプロジェクトの「参照」で、F#のプロジェクト自体を参照させる。
    ※Visual StudioS2015 ではエラーが発生し、できませんでした。

  4. F# のコードを書く。
    例を示します。デフォルトコンストラクタと、intとstring を返すメソッドを持つ簡単なクラスです。

namespace LibrarySpace 

type FSharpLibrary = class
  val intA: int
  val stringA: string 

  (* default constructor *)
  new () = {
    intA = 10
    stringA = "String#10"
  }

  (* return in *)
  member this.getIntA = this.intA

  (* return string *)
  member this.getStringA = this.stringA

  end;;

5.C++/CLIのコードを書く。コンソールアプリです。このコードでF#の
"LibrarySpace"名前空間のFSharpLibraryクラスのインスタンスへアクセスします。

// C++/CLI
#include "stdafx.h"
#include <vcclr.h>  // PtrToStringChars()
#include <stdio.h>  // wprintf()

using namespace System;
using namespace LibrarySpace;

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Hello");

    FSharpLibrary^ lib = gcnew FSharpLibrary();

    // getIntAメソッド呼び出し
    int num = lib->getIntA;

    // getStringA メソッド呼び出し
    System::String^ s = lib->getStringA;
    Console::WriteLine(s);

    // Cランタイムで文字列を表示
    wchar_t* ps = (wchar_t*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(s).ToPointer();
    wprintf(L"printf: %s\n", ps);
    System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(ps));

  Console::WriteLine(L"End");
  return 0;
}

これで、F#のLibrarySpace::FSharpLibraryクラスのgetIntA, getStringAメソッドを
呼び出せることを確認できました。名前空間(例では"LibrarySpace")に注意してください。
正しく参照できていれば、Visual Studioのインテリセンスで自動的にシンボルが
入力できるようになります。

例のコードで分かるように、C++/CLI側のコードでは、例えばchar* やwchar_t 等の
ネイティブの文字列を扱うときには .NET Framework のSystem::Stringとchar* 等を
相互変換する必要があります。面倒くさいので、適切なラッパー関数を更に書く必要が
あるかもしれません。

また、上記のテストプロ含め、F#<-->C++/CLI間での簡単なやり取りしか確認していません。
F#でのタプル等の複雑な入出力が扱えるかは未確認です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/02 10:11

    ご回答ありがとうございます。
    お忙しい中で大変丁寧にお答えいただいたところ恐縮ですが、呼び出す側の言語はC++/CLI(visual C++)になります。
    C++/CLI(visual C++)からの呼び出し方も教えていただけないでしょうか。

    自分の質問の書き方が不正確なばかりに申し訳ございません。

    キャンセル

  • 2017/10/03 17:11

    Visual Studio 2012 のC++/CLI, F#で確認したものを追記しました。

    キャンセル

  • 2017/10/03 17:13

    たいへん丁寧なご回答ありがとうございます。
    Visual Studio2013でやってみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.02%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C++

    2930questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • F#

    7questions

    F#は、MicroSoftが開発した.NET Framework 向けのマルチパラダイムプログラミング言語です。 Visual Studio 2010 より標準搭載されました。