How i can reference my plugin?

I need to reference my *.rhp file but VS is saying that file cannot be added - if i rename it to *.dll it works fine - is there any workaround for this?

If i try to reference it from c++/cli vs isn’t complaining but during runtime it tells that file doesn’t exists - unless i’ll rename file to *.dll … For rhp i get exacly this:

Exception not handled: System.IO.FileNotFoundException:

@dale @stevebaer @pascal

The correct way to doing this is to put functionality in a DLL, then have your RHP only contain calls into your DLL.

You can reference your RHP directly as well, but you’ll need to manually edit the project file for that.

Here a short example for one that references RhinoCycles.rhp in an empty C# .NET console project.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{84BD456C-E9D1-45DD-9C28-4B38BEAC6F33}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>QuickRefereneTest</RootNamespace>
    <AssemblyName>QuickRefereneTest</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="RhinoCycles">
      <HintPath>D:\Dev\Rhino\rhino\src4\bin\Debug\Plug-ins\RhinoCycles.rhp</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
1 Like

Thank you Nathan very much for info on this in terms of C# this will be handy for me soon. I wonder if there is similar workaround for C++/CLI.

I don’t know about you, but I just tried to add RhinoCycles.rhp as a reference in a clean C++/CLR project. VS allowed me to do that without any problems…

Sure VS allows to do this but during runtime i get above exception in console app. For now i found i can use:

#using “fixed/path/to/file/plugin.rhp”

[EDIT] My bad this also don’t work i’ve left dll file thats why it worked. So i’m still looking for workaround.

Well it only bypassed VS complains but at runtime gives exactly the same error as earlier…

@nathanletwory would you mind to call some static method from this console app? I get exactly this at runtime:

Additional information: Cannot load file 'MyPlugin, Version=0.0.6856.20507, Culture=neutral, PublicKeyToken=null' or one of its dependencies. File not found.

I don’t know how this is supposed to work. I haven’t used C++/CLI before.

@nathanletwory i get the same error even in c# console app just when calling simple static method for eg.

in rhp.

public static int Add(int a, int b)
{
return a+b;
}

in console app:

Console.WriteLine(Namespace.StaticClass.Add(2,4));
Console.ReadLine();

@nathanletwory @dale Guys can someone confirm above? I’d like to know if this is sys dependant or what…

Hi @D-W,

If I understand correctly, you are trying to reference a RhinoCommon plug-in, which is dependent on a running Rhino.exe, into a console application?

– Dale

Hi @dale,

i’m trying to test if my reverse p/invoke works like it should. Case here is that it looks like extension matters if i try to reference my plugin with *.rhp i get exception but if i rename manually back to dll it works fine. So i don’t know if this is only my sys case or this is also happening elsewhere.

I would understand if it would only behave lkie this when i’m doing c++/cli things but i tried what @nathanletwory said and i edited csproj in normal c# console template and VS doesn’t complain inteliSense is ok but during runtime it says that file cannot be found.

I believe that D-W is trying to make his plug-in available to C++ plug-ins. If that is the case, then telling C++ developers to use C++/CLI probably isn’t going to fly. I would recommend creating a class that represents your SDK and is returned from your plug-in through the plug-in’s virtual GetPlugInObject function. There are ways to make this class COM callable through IDispatch which is how C++ plug-ins could then use your SDK. @dale do we have any docs or samples laying around for C++ plug-ins using SDKs from other plug-ins provided through the GetPlugInObject function? I haven’t looked at this stuff for a long time

@stevebaer c++/cli is my middle layer i’m passing methods further to unmanaged code and it looks that everything is ok but only if i rename manualy rhp to dll - in c# as above i have the same case. But of course if there is any internal way to handle this it should be better.

I don’t believe we have any modern guides that discuss this. But if you look through the samples repository (search for GetPlugInObjectInterface in the C++ samples and GetPlugInObject in the C# samples), you will find some samples. However, dealing with COM in C++ is really painful…

GitHub - mcneel/rhino-developer-samples: Rhino and Grasshopper developer sample code

– Dale

I agree it is painful, but D-W could write a single C++ source file that handles all of the complexities and just makes everything look like a handful of functions. It is simply an option, I don’t know if it is the best one.

Anything is ok if it works. But i still don’t know if there is any way of adding a reference to rhp (which is dll) - so it is fully capable of being just a library.

GetPlugInObject gets around this dependency issue which is why I brought it up. If your plug-in is installed, Rhino will load it and call the appropriate function for handing a class back to the calling C++ plug-in.

I believe that making another dll which will be a dependency of the plugin and will handle reverse p/invoke will be much easier to manage than doing this via internals which i don’t have a clue how should behave.

There is also an option for regular p/invoke and handling stuff directly in c++ which i would place somewhere in the middle in terms of difficulty.

Any other ideas?

I typically stay far away from C++/CLI since it locks you into the Windows platform, but that may not be a problem in your case. If you want to use C++/CLI, I would investigate exporting some C functions from the DLL using extern C. You could then write a small C++ source file that loads your DLL and calls the exported C functions.

1 Like

Hmm … Noob question: should i use extern C or __declspec(dllexport) ? AFAIK extern C is just for C and __declspec(dllexport) is for C++ but i can be wrong… And next noob question: as i understand c++ cant handle dependencies with given path so basicaly that means that my plugin will call dll in its dir and other plug will call dll in its dir - Will those be treated as the same dll in term of passing objects under one process ?

What kind of functions are you trying to provide? Maybe we can step back and approach the problem from a different direction.

All of this is very difficult to do. Maybe we can figure out an alternative technique.