I am performing a project with ITK for processing medical images. After a lot of work there is no further compilation errors, but in the linking process I am having the following info :
1>------Generation started: proyect: prueba_r01, configuration: Debug Win32 ------
1>Linking…
1>Creating library C:\Documents and Settings\GTTS\Mis documentos\Visual Studio 2008\Projects\prueba_r01\Debug\prueba_r01.lib and object C:\Documents and Settings\GTTS\Mis documentos\Visual Studio 2008\Projects\prueba_r01\Debug\prueba_r01.exp
1>prueba_r01.obj : error LNK2019: extern symbol "public: double (* __thiscall prueba_r01::multiply_matrix_2D(double ()[2],double ()[2],int,int))[2]" (?multiply_matrix_2D#prueba_r01##QAEPAY01NPAY01N0HH#Z) unresolved which is referenced in the function "private: void __thiscall prueba_r01::filtro(void)" (?filtro#prueba_r01##AAEXXZ)
1>C:\Documents and Settings\GTTS\Mis documentos\Visual Studio 2008\Projects\prueba_r01\Debug\prueba_r01.exe : fatal error LNK1120: 1 externos sin resolver
1>prueba_r01 - 2 errors, 0 warnings
========== Generar: 0 corrects, 1 incorrects, 0 actualized, 0 omited ==========
The method multiply_matrix_2D produces the error when is called inside the private slot “filtro()” (translated as filter)
The header of the file is :
#include <QtGui/QMainWindow>
#include "ui_prueba_r01.h"
#include "vicdef.h"
#include "itkImage.h"
#include "math.h"
#include <complex>
#include "fftw3.h"
using namespace std;
#define PI 3.14159265
class prueba_r01 : public QMainWindow
{
Q_OBJECT
public:
typedef double PixelType;
typedef itk::Image < PixelType, 2> ImageType;
ImageType::Pointer imagen;
double** H;
prueba_r01(QWidget *parent = 0, Qt::WFlags flags = 0);
~prueba_r01();
void matrix2D_H(int ancho, int alto, double eta, double sigma);
fftw_complex* multiply_matrix_2D(fftw_complex* out, fftw_complex* H,int a, int b);
private slots:
void openRGB();
void filtro();
private:
Ui::prueba_r01Class ui;
};
#endif // PRUEBA_R01_H
And the main part where the problem is located is in the .cpp file and is displayed here:
fftw_complex* res ;
res = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*a*b);
fftw_complex* H_casted= reinterpret_cast<fftw_complex*> (&H);
res = multiply_matrix_2D(out,H_casted, a, b);
The process of casting a **double pointer to *fftw_complex is done here, because I want to multiply a filter in frequency domain (H(w)) with the result of the fft transform of an image, that’s the reason. Is important to remark that fftw_complex is double[2], the first row for the real part, and the second for the imaginary
And the problematic method is shown below:
fftw_complex* multiply_matrix_2D(fftw_complex* out, fftw_complex* H, int a ,int b){
/* The matrix out[axb] or [n0x(n1/2)+1] is the image after the FFT , and the out_H[axb] is the filter in the frequency domain,
both are multiplied POINT TO POINT, it has to be called twice, one for the imaginary part and another for the normal part
*/
fftw_complex *res;
res = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*a*b);
for (int i0 = 0; i0<a ; i0++){
for (int i1 = 0; i1<b ; i1++){
res[i1+a*i0][0] = out[i1+a*i0][0]*(H[0][0]+H[0][1]); // real part
res[i1+a*i0][1] = out[i1+a*i0][1]*(H[0][0]+H[0][1]); // imaginary part
}
}
return res;
}
Any help will be really nice!! I’m quite lost now…
Thanks! Gracias!
Antonio
Change the function header in the cpp file to:
fftw_complex* prueba_r01::multiply_matrix_2D(fftw_complex* out, fftw_complex* H, int a, int b)
You forgot the class name (prueba_r01::) in the implementation, therefore it doesn't find the function body
Related
There are quite a lot similar posts concerning this topic here on SO, however so far I couldn't find a solution to my issue.
I want to add CUDA functionality to an existing C++ project (Window, Visual Studio 2019). Here is what I did so far (based on what I gathered googling around).
Solution Explorer -> Right-Click on Project -> Build Dependencies -> Build Customization -> Tick Checkbox for CUDA 11.2 (.targets, .props)
Created a new 'dummy' CUDA project from Visual Studio, build and started it (VS2019 creates a small project, which adds items of two arrays using CUDA on the GPU). It worked.
Checked and compared Project properties between my existing project and the 'dummy' project and changed the following options:
CUDA C/C++ -> Target Machine Platform -> 64-Bit
Linker -> Additional Dependencies -> added cudart_static.lib
Next I created a class with some test code (which is pretty much completely taken from the 'dummy' project):
SHCalculator.h:
#pragma once
class SHCalculator
{
private:
public:
void DoTestCalculationWithCuda();
};
SHCalculator.cpp:
#include "pch.h"
#include "SHCalculator.h"
#include "SHCalculation.cuh"
void SHCalculator::DoTestCalculationWithCuda()
{
const int arraySize = 5;
const int a[arraySize] = { 1, 2, 3, 4, 5 };
const int b[arraySize] = { 10, 20, 30, 40, 50 };
int c[arraySize] = { 0 };
cudaError_t cudaStatus = AddWithCuda(c, a, b, arraySize);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "addWithCuda failed!");
return;
}
printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
c[0], c[1], c[2], c[3], c[4]);
// cudaDeviceReset must be called before exiting in order for profiling and
// tracing tools such as Nsight and Visual Profiler to show complete traces.
cudaStatus = cudaDeviceReset();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaDeviceReset failed!");
return;
}
}
SHCalculation.cuh:
cudaError_t AddWithCuda(int* c, const int* a, const int* b, unsigned int size);
//__global__ void addKernel(int* c, const int* a, const int* b);
SHCalculation.cu:
#include "pch.h"
#include "SHCalculation.cuh"
//__global__ void addKernel(int* c, const int* a, const int* b)
//{
// int i = threadIdx.x;
// c[i] = a[i] + b[i];
//}
cudaError_t AddWithCuda(int* c, const int* a, const int* b, unsigned int size)
{
int* dev_a = 0;
int* dev_b = 0;
int* dev_c = 0;
cudaError_t cudaStatus = cudaError_t::cudaErrorAssert;
// left out all the other code (memory allocation, kernel calling) here, since the error
// comes without it as well.
return cudaStatus;
}
Notice, I have commented out or removed a lot of the code, as the error appears regardless. This are the error messages:
LNK2019 unresolved external symbol "enum cudaError __cdecl AddWithCuda(int *,int const *,int const *,unsigned int)" (?AddWithCuda##YA?AW4cudaError##PEAHPEBH1I#Z) referenced in function "public: void __cdecl SHCalculator::DoTestCalculationWithCuda(void)" (?DoTestCalculationWithCuda#SHCalculator##QEAAXXZ)
LNK1120 1 unresolved externals
Additional Info:
CUDA includes are in the precompiled header pch.h:
// cuda
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
What could be the reason for the linker error?
Here is what was missing:
For all CUDA files do:
Right-Click -> Properties
In Configuration Properties -> General -> Item Type choose CUDA C/C++
This is the reason that no *.obj files where created and the linker couldn't link them.
This error was thrown by my code:
1>MSVCRTD.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ)
1>C:\Users\thequantumforge\Desktop\scripts\Visual Studio 2013\Projects\newtonsmethod\x64\Debug\newtonsmethod.exe : fatal error LNK1120: 1 unresolved externals
The code is as follows:
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <cmath>
#include <cfloat>
#include <chrono>
using namespace std;
const long double h = LDBL_EPSILON;
long double equation(long double x) {
return (pow(x, 3) - x + 1);
}
long double intercept(long double x) {
// x_n+1 = xn - f(xn)/f'(xn)
long double deriv = (equation(x + h) - equation(x)) / h;
if (deriv == 0)
{
x += h;
return (x - equation(x) / ((equation(x + h) - equation(x)) / h));
}
return (x - equation(x) / deriv);
int main() {...}
It worked in Code::Blocks using the C++11 compiler, so I'm not sure why it isn't working with Visual Studio 2015. I tried looking at other answers, but those were either unclear or were for other versions of Visual Studio. I did some research and found out that it's supposed to be caused by a misspelling of the main() function, but that doesn't seem to be the case. I tried declaring the function prototypes first then defining them after main(), but the result is the same.
Change your solution into a console application in the linker => system section:
I am trying to modify some sample code of matlab showing use of mex file.
I tried to include armadillos library (http://arma.sourceforge.net/docs.html) without any success.
Though I did found one similar questions on this website; however, the answers were not helpful. So, I would appreciate some help.
I usually include armadillos without any problem as follows in my other visual C++ codes:
#define ARMA_64BIT_WORD
#include " C:\MIDEA\N4_VD13A_LATEST_20120616\n4\pkg\MrServers\MrImaging\seq\UserLib_DK\armadillo-3-910-0\include\armadillo"
using namespace arma;
However, when I do the same with “sincall.c”, it returns me error (multiple instances):
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\cstdlib(21) : error C2143: syntax error : missing '{' before ':'
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\cstdlib(21) : error C2059: syntax error : ':
My code looks like this:
#include "mex.h"
#define MAX 1000
// #include armadillo
#define ARMA_64BIT_WORD
#include " C:\MIDEA\N4_VD13A_LATEST_20120616\n4\pkg\MrServers\MrImaging\seq\UserLib_DK\armadillo-3-910-0\include\armadillo"
using namespace arma;
/* subroutine for filling up data */
void fill( double *pr, mwSize *pm, mwSize *pn, mwSize max )
{
mwSize i;
/* you can fill up to max elements, so (*pr)<=max */
*pm = max/2;
*pn = 1; // DK: it means that it's 1D array
for (i=0; i < (*pm); i++)
{
pr[i]=i*(4*3.14159/max);
}
}
/* gateway function */
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
{
mwSize m, n, max=MAX;
mxArray *rhs[1], *lhs[1];
(void) nlhs; (void) plhs; /* unused parameters */
(void) nrhs; (void) prhs;
rhs[0] = mxCreateDoubleMatrix(max, 1, mxREAL);
/* pass the pointers and let fill() fill up data */
fill(mxGetPr(rhs[0]), &m, &n, MAX);
mxSetM(rhs[0], m);
mxSetN(rhs[0], n);
/* get the sin wave and plot it */
mexCallMATLAB(1, lhs, 1, rhs, "sin");
mexCallMATLAB(0, NULL, 1, rhs, "plot");
/* cleanup allocated memory */
mxDestroyArray(rhs[0]);
mxDestroyArray(lhs[0]);
return;
}
First few lines of armadillos header file is:
#ifndef ARMA_INCLUDES
#define ARMA_INCLUDES
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cmath>
Regards,
DK
I am trying to create a CUDA + C++ project. Basically a .cpp project that calls for some CUDA kernel. So I simply followed the example here, which basically adds two vectors. The kernel does the summation job:
http://blog.norture.com/2012/10/gpu-parallel-programming-in-vs2012-with-nvidia-cuda/
Here is the code,
#include <iostream>
#include "cuda_runtime.h"
#include "cuda.h"
#include "device_launch_parameters.h"
using namespace std;
__global__ void saxpy(int n, float a, float *x, float *y)
{
int i = blockIdx.x*blockDim.x + threadIdx.x;
if (i < n) y[i] = a*x[i] + y[i];
}
int main(void)
{
int N = 1<<20;
float *x, *y, *d_x, *d_y;
x = (float*)malloc(N*sizeof(float));
y = (float*)malloc(N*sizeof(float));
cudaMalloc(&d_x, N*sizeof(float));
cudaMalloc(&d_y, N*sizeof(float));
for (int i = 0; i < N; i++) {
x[i] = 1.0f;
y[i] = 2.0f;
}
cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);
// Perform SAXPY on 1M elements
saxpy<<<(N+255)/256, 256>>>(N, 2.0, d_x, d_y);
cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);
float maxError = 0.0f;
for (int i = 0; i < N; i++)
maxError = max(maxError, abs(y[i]-4.0f));
cout << "Max error: " << maxError;
}
When I built I got this error:
1>------ Rebuild All started: Project: CUDATest001, Configuration: Debug x64 ------
1> CUDATestZeroZeroOne.cpp
1>CUDATestZeroZeroOne.obj : error LNK2001: unresolved external symbol threadIdx
1>CUDATestZeroZeroOne.obj : error LNK2001: unresolved external symbol blockIdx
1>CUDATestZeroZeroOne.obj : error LNK2001: unresolved external symbol blockDim
1>D:\Projects\CUDATest001\x64\Debug\CUDATest001.exe : fatal error LNK1120: 3 unresolved externals
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
If the line saxpy<<<(N+255)/256, 256>>>(N, 2.0, d_x, d_y); is commented out, then this error appeared:
1>------ Rebuild All started: Project: CUDATest001, Configuration: Debug x64 ------
1> CUDATestZeroZeroOne.cpp
1>CUDATestZeroZeroOne.obj : error LNK2001: unresolved external symbol threadIdx
1>CUDATestZeroZeroOne.obj : error LNK2001: unresolved external symbol blockIdx
1>CUDATestZeroZeroOne.obj : error LNK2001: unresolved external symbol blockDim
1>D:\Projects\CUDATest001\x64\Debug\CUDATest001.exe : fatal error LNK1120: 3 unresolved externals
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
I am using vs2012 + CUDA 5.5. I started with a empty C++ win32 console project, added a .cpp file which includes all the code above. I am not even sure at this point should it be a .cu or a .cpp file?
Anyone has any idea how to make this work? Thanks.
In the context menu for your project, click Build Customizations. Turn on the CUDA 5.5 target.
In the context menu for your .cpp file, click Rename and rename it to .cu.
In the context menu for your .cu file (that you just renamed), select Properties. Then go to General and make sure Item Type is set to CUDA C/C++.
Rebuild.
When you start a new CUDA project, you can select Templates > NVIDIA > CUDA 5.5 > CUDA 5.5 Runtime to get a project that should compile without any modifications.
I just completed a proof of concept, or so I thought, of feeding Microsoft Visual Studio 2010 some C++ code as a console program. The C++ code that compiled is given below:
#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <sndfile.h>
//The following libraries are related to parsing the text files
#include <iostream> //Open the file
#include <fstream> //Reading to and from files
//The following libraries are for conducting the DTW analysis
#include "dtw.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
printf("This is a test\n");
//This will be the length of the buffer used to hold samples while the program processes them.
//A SNDFILE is like FILE in a standard C library. Consequently, the sf_open_read and sf_open_write functions will return an
//SNDFILE* pointer when they successfully open the specified file.
SNDFILE* sf = NULL;
/*SF_INFO will obtain information of the file we wish to load into our program. */
SF_INFO info;
/*The following is descriptive information to obtain from wave files. These are declarations*/
int num_channels;
double num, num_items;S
double *buf;
int f, sr, c;
int i,j;
FILE *out;
/*This is where the program will open the WAV file */
info.format = 0;
sf = sf_open("C:\\Users\\GeekyOmega\\Desktop\\gameon.wav", SFM_READ, &info);
if(sf == NULL)
{
printf("Failed to open the file.\n");
getchar();
exit(-1);
}
/*Print some file information */
f = info.frames;
sr = info.samplerate;
c = info.channels;
/*Print information related to file*/
printf("frames = %d\n",f);
printf("sample rate = %d\n",sr);
printf("channels = %d\n",c);
/*Calculate and print the number of items*/
num_items = f*c;
printf("Read %lf items\n", num_items);
/*Allocate space for the data to be read*/
buf = (double *) malloc(num_items*sizeof(double));
num = sf_read_double(sf,buf,num_items);
sf_close(sf);
/*print the information*/
printf("Read %lf items\n", num);
/*Write the data to the filedata.out*/
out = fopen("filedata.txt", "w");
for(i = 0; i < num; i+=c)
{
for(j = 0; j < c; ++j)
{
fprintf(out, "%lf ", buf[i +j]);
}
fprintf(out,"\n");
}
fclose(out);
}
So next, and this is critical, I want this to work with a GUI. That is, I load in any file I want and it converts that wav file to text. I provide that code below:
#pragma once
//Libraries required for libsndfile
#include <sndfile.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
namespace WaveGui {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Runtime::InteropServices;
using namespace std;
/// <summary>
/// Summary for Form1
/// </summary>
I edited this for readability. It was a standard MSVS2010 form. I only added a button and open file dialog.
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
if(openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
//Note: Ask Gustafson how we might free the memory for this strign
// http://support.microsoft.com/?id=311259
char* str2 = (char*)(void*)Marshal::StringToHGlobalAnsi(openFileDialog1->FileName);
SNDFILE* sf = NULL;
SF_INFO info;
/*The following is descriptive information to obtain from wave files. These are declarations*/
int num_channels;
double num, num_items;
double *buf;
int f, sr, c;
int i,j;
FILE *out;
/*This is where the program will open the WAV file */
info.format = 0;
sf = sf_open(str2, SFM_READ, &info);
if(sf == NULL)
{
exit(-1);
}
/*Print some file information */
f = info.frames;
sr = info.samplerate;
c = info.channels;
/*Calculate and print the number of items*/
num_items = f*c;
/*Allocate space for the data to be read*/
buf = (double *) malloc(num_items*sizeof(double));
num = sf_read_double(sf,buf,num_items);
sf_close(sf);
/*Write the data to the filedata.out*/
out = fopen("filedata.txt", "w");
for(i = 0; i < num; i+=c)
{
for(j = 0; j < c; ++j)
{
fprintf(out, "%lf ", buf[i +j]);
}
fprintf(out,"\n");
}
fclose(out);
}
}
};
}
In the code for the button, I convert from a system string to regular string and then try to use the C++ code above to convert my wave file to txt information. I know the conversion code works, and I know the button code works as I have tested them separately. However, my library sndfile.h really dies when I try to use it now.
The error it gives me when I added the libraries stdio.h, Windows.H, stdlib.h, iostream, fstream is as follows:
1>WaveGui.obj : error LNK2031: unable to generate p/invoke for "extern "C" int __clrcall sf_close(struct SNDFILE_tag *)" (?sf_close##$$J0YMHPAUSNDFILE_tag###Z); calling convention missing in metadata
1>WaveGui.obj : error LNK2031: unable to generate p/invoke for "extern "C" __int64 __clrcall sf_read_double(struct SNDFILE_tag *,double *,__int64)" (?sf_read_double##$$J0YM_JPAUSNDFILE_tag##PAN_J#Z); calling convention missing in metadata
1>WaveGui.obj : error LNK2031: unable to generate p/invoke for "extern "C" struct SNDFILE_tag * __clrcall sf_open(char const *,int,struct SF_INFO *)" (?sf_open##$$J0YMPAUSNDFILE_tag##PBDHPAUSF_INFO###Z); calling convention missing in metadata
1>WaveGui.obj : warning LNK4248: unresolved typeref token (01000027) for 'SNDFILE_tag'; image may not run
1>WaveGui.obj : error LNK2028: unresolved token (0A000022) "extern "C" int __clrcall sf_close(struct SNDFILE_tag *)" (?sf_close##$$J0YMHPAUSNDFILE_tag###Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click#Form1#WaveGui##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
1>WaveGui.obj : error LNK2028: unresolved token (0A000023) "extern "C" __int64 __clrcall sf_read_double(struct SNDFILE_tag *,double *,__int64)" (?sf_read_double##$$J0YM_JPAUSNDFILE_tag##PAN_J#Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click#Form1#WaveGui##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
1>WaveGui.obj : error LNK2028: unresolved token (0A000025) "extern "C" struct SNDFILE_tag * __clrcall sf_open(char const *,int,struct SF_INFO *)" (?sf_open##$$J0YMPAUSNDFILE_tag##PBDHPAUSF_INFO###Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click#Form1#WaveGui##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
1>WaveGui.obj : error LNK2019: unresolved external symbol "extern "C" int __clrcall sf_close(struct SNDFILE_tag *)" (?sf_close##$$J0YMHPAUSNDFILE_tag###Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click#Form1#WaveGui##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
1>WaveGui.obj : error LNK2019: unresolved external symbol "extern "C" __int64 __clrcall sf_read_double(struct SNDFILE_tag *,double *,__int64)" (?sf_read_double##$$J0YM_JPAUSNDFILE_tag##PAN_J#Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click#Form1#WaveGui##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
1>WaveGui.obj : error LNK2019: unresolved external symbol "extern "C" struct SNDFILE_tag * __clrcall sf_open(char const *,int,struct SF_INFO *)" (?sf_open##$$J0YMPAUSNDFILE_tag##PBDHPAUSF_INFO###Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click#Form1#WaveGui##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
1>c:\users\geekyomega\documents\visual studio 2010\Projects\WaveGui\Debug\WaveGui.exe : fatal error LNK1120: 6 unresolved externals
As near as I can tell, I installed the library right. After all, it works perfectly fine with these libraries in a console situation. However, when I try to use the exact same code and libraries with my GUI form, it seems that the libraries are not playing nice with each other and as a result, I can't read my .h file right and access structs like SNDFILE.
Can someone please let me know what is going wrong? I have spent hours on this and I hope I don't have to scrap the libsndfile library. I really want to get it to work with MSVS2010, with the GUI and as far as I can tell, there is no reason this shouldn't be working. But you know what they say, computers don't lie.
As always, thanks for your patient help.
GeekyOmega
So, your console app is native code, but your GUI app is managed C++. Was that intentional, or did you intend for your GUI app to be native (Win32) code too?
I think you'll have better luck if you either go with 100% native code, or perhaps create a DLL to encapsulate your native code and call that via P/Invoke from your .NET GUI. Here's an example of using P/Invoke:
http://manski.net/2012/05/29/pinvoke-tutorial-basics-part-1/